c++ - Socket select() 第二次阻塞

标签 c++ sockets networking tcp

我正在开发一个简单的服务器/客户端程序。我正在使用 select() 等待数据在读取数据之前进入 TCP 套接字。当数据进入时,我使用几个 recv()select() 调用以读入 block ,直到我拥有所有内容。然后我循环回到最初的 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 位机器上运行失败。我仍然没有解决问题,但这大大缩小了范围。

最佳答案

在没有看到完整代码的情况下,很难判断哪里出了问题。但是,select() 函数修改 传递给它的fd_set 值。您需要确保在调用 select() 之前重新初始化每个 fd_set 值,以便包含所需的套接字。

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

关于c++ - Socket select() 第二次阻塞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8106905/

相关文章:

c++ - 在 C++ 中删除一个 tbb 线程

c++ - cpp中的接口(interface)

Python 套接字 Recv 无法正常工作有人可以解释

C Unix套接字编程,确保读/写字节数?

android - java.net.绑定(bind)异常 : bind failed: EADDRINUSE (Address already in use)

java - 如何测量使用UDP协议(protocol)通信的服务器和客户端之间的响应时间?

c++ - QChar::isDigit() 和 QChar::isNumber() 有什么区别?

c++ - 指针与引用

java - 如何发送二进制格式的Java对象并在C服务器中接收?

c sendfile 第二次不起作用