如何在Windows中退出阻塞recv()?

时间:2016-08-13 19:10:05

标签: c multithreading sockets winapi winsock

我有一个包含阻止recv()调用的线程,如下所示:

{   
    while(1)
    {
        recv(socket, buffer, sizeof(buffer), 0);
    }       
}

现在我想做的是从另一个线程发出recv()函数信号,使其退出阻塞状态。我从另一个讨论如何在Unix中执行此操作的问题中阅读了以下答案(How to let a thread which blocks on recv() exit gracefully?):

  

或者:

     
      
  1. 使用setsockopt()SO_RCVTIMEO设置读取超时,并在触发时检查状态变量以查看您是否已被告知   你自己停止阅读。
  2.   
  3. 如果您想要永久停止阅读套接字,请将其关闭,以便使用shutdown(sd, SHUT_RD)进行输入。这将导致recv()返回   从现在开始为零。
  4.   
  5. 将套接字设置为非阻塞模式,并使用select()超时告诉您何时阅读,采用相同的策略   状态变量如上面的(1)所述。然而,非阻塞模式引入   相当复杂的发送操作,所以你应该   更喜欢上面的(1)或(2)。
  6.         

    您的伪代码缺少EOS和错误检查。我希望它没有   真的很像。

我对第一个和第三个解决方案不感兴趣,因为CPU可能会耗尽,根据我的测试,Windows不支持第二个解决方案(我是对的吗?)。那么还有另一种退出阻止recv()的解决方案吗?

1 个答案:

答案 0 :(得分:4)

阻止 recv()仅在以下时退出:

  1. 读取数据。

  2. 读取超时(SO_RCVTIMEO)。

  3. 连接已关闭。

  4. 如果这些选项都不适合您,则必须在阻止模式下调用recv(),直到您知道有等待阅读的内容,如select()所报告的那样WSAAsyncSelect() 1}},或WSAEventSelect()

    否则,将套接字逻辑重写为:

    1. 以非阻塞模式使用套接字。

    2. WSARecv()RIOReceive/Ex()与重叠I / O或I / O完成端口一起使用。可以使用CancelIo/Ex()取消I / O操作。

相关问题