套接字select()第二次阻塞

时间:2011-11-12 19:17:33

标签: c++ sockets networking tcp

我有一个简单的服务器/客户端程序,我正在处理。我在使用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 个答案:

答案 0 :(得分:3)

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

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