我有一个简单的服务器/客户端程序,我正在处理。我在使用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位计算机上运行失败。我仍然无法解决这个问题,但这会让它缩小一点。
答案 0 :(得分:3)
如果没有看到完整的代码,很难说出可能出现的问题。但是,select()
函数会修改传递给它的fd_set
值。在调用fd_set
之前,您需要确保重新初始化每个select()
值,以便包含所需的套接字。
还要记住,recv()
函数将阻塞,直到它获得某些数据(或套接字已关闭),因此除非你真的需要超时功能,否则你甚至不需要调用{ {1}}。最后,如果任何数据可用,select()
函数将返回,而不一定所有您要求的数据。您必须在循环中重复调用recv()
以获取所有数据。 即使您正在读取少量字节,也是如此。