2011-11-12 87 views
1

我有一个简单的服务器/客户端程序,我正在处理。我正在使用select()等待数据在读取之前进入TCP套接字。当数据进入时,我使用几个recv()select()调用来读取块,直到我拥有了全部数据。然后,我循环回到最初的select()调用,并查看客户端是否有其他要发送的内容。套接字选择()第二次阻塞

struct timeval timeoutCounter; 
fd_set readFileDescriptor; 
do { 
    timeoutCounter.tv_sec = 30; 
    timeoutCounter.tv_usec = 0; 
    FD_ZERO(&readFileDescriptor); 
    FD_SET(socket, &readFileDescriptor); 
    cout << "This line always prints, every iteration through the loop.\n"; 
    dataReady = select(socket+1,&readFileDescriptor,NULL,NULL,&timeoutCounter); 
    cout << "This line only prints the first time I call select()." 
     << "The second time it hangs before reaching this line.\n"; 

    // ... recv(), select(), recv(), select(), etc in a loop until I have all the data 
    // send() a response to the client 
} while(dataReady > 0); 

我开始了与所有这一切都在一个大,难以读取功能,和它的工作。然后我把它分解成一个独立的类,与accept()的联系,现在它的行为是不同的。用户发送的第一个数据集正常。但客户端等待来自服务器的响应,然后将第二组数据发送到套接字。但是,客户端发送第二组数据后,select()不会返回;它阻塞,直到它超时。

我已经认定客户是问题所在;数据包会在适当的时候正常发送。我也尝试打印套接字文件描述符来证明它不会在某处发生更改。有谁知道为什么这段代码可能不起作用吗?可能导致select()阻止的因素有哪些?

编辑:它看起来像我的代码运行在32位机器很好,但未能在64位机器。我仍然没有解决这个问题,但是这个问题缩小了一点。

+1

像某人的声音正在破坏'socket'变量。尝试使用strace(1)运行服务器,以确保选择和recv的所有参数都符合您的期望。或者单步调试器中的服务器,检查系统调用参数 –

回答

3

如果没有看到完整的代码,很难说出可能的错误。但是,select()函数修改了传递给它的值fd_set。在调用select()之前,您需要确保重新初始化每个fd_set值,以便包含所需的套接字。

也要记住,recv()函数将阻塞,直到它得到一些数据(或关闭套接字)所以,除非你真的需要超时功能,你甚至可能不会需要调用select()。最后,recv()功能将返回,如果任何数据可用,不一定所有你所要求的。您将不得不在循环中重复呼叫recv()以获取所有数据。 即使读取少量字节,情况也是如此。

+0

是的,我知道。代码本身非常长 - 我们正在谈论数百行,其中大部分都是错误检查。如果人们真的想要通过它,我可以发布它。 虽然我在那里重置fd_set值 - 就在我调用select之前,我总是调用FD_ZERO和FD_SET –