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

如何在Windows中退出阻止recv()?,c,multithreading,sockets,winapi,winsock,C,Multithreading,Sockets,Winapi,Winsock,我有一个线程,它包含一个blockingrecv()调用,类似这样: { while(1) { recv(socket, buffer, sizeof(buffer), 0); } } 现在我要做的是从另一个线程向recv()函数发送信号,使其退出阻塞状态。我已经从另一个关于如何在Unix()中执行此操作的问题中阅读了以下答案: 要么: 使用setsockopt()和SO\u RCVTIMEO设置读取超时,每当它触发时,检查状态变量以

我有一个线程,它包含一个blocking
recv()
调用,类似这样:

{   
    while(1)
    {
        recv(socket, buffer, sizeof(buffer), 0);
    }       
}
现在我要做的是从另一个线程向
recv()
函数发送信号,使其退出阻塞状态。我已经从另一个关于如何在Unix()中执行此操作的问题中阅读了以下答案:

要么:

  • 使用
    setsockopt()
    SO\u RCVTIMEO
    设置读取超时,每当它触发时,检查状态变量以查看是否已告知 让你自己停止阅读
  • 如果要永远停止读取套接字,请使用
    shutdown(sd,shuth\u RD)
    将其关闭以进行输入。这将导致
    recv()
    返回 从现在开始零
  • 将套接字设置为非阻塞模式,并使用带有超时的
    select()
    来告诉您何时读取,使用与 如上(1)所述的状态变量。然而,非阻塞模式引入了 send手术相当复杂,所以你应该 优先选择(1)或(2)以上
  • 您的伪代码缺少EOS和错误检查。我希望不会 真像那样

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

    只有在以下情况下,阻塞
    recv()
    才会退出:

  • 数据被读取

  • 读取超时(SO_RCVTIMEO)

  • 连接已关闭

  • 如果这些选项对您都不可行,您将不得不在阻塞模式下不调用
    recv()
    ,直到您知道有东西等待读取,如
    select()
    WSAAsyncSelect()
    WSAEventSelect()
    所述

    否则,请将套接字逻辑重新写入:

  • 在非阻塞模式下使用套接字

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

  • 阻塞
    recv()
    仅在以下情况下存在:

  • 数据被读取

  • 读取超时(SO_RCVTIMEO)

  • 连接已关闭

  • 如果这些选项对您都不可行,您将不得不在阻塞模式下不调用
    recv()
    ,直到您知道有东西等待读取,如
    select()
    WSAAsyncSelect()
    WSAEventSelect()
    所述

    否则,请将套接字逻辑重新写入:

  • 在非阻塞模式下使用套接字

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


  • 选项#3是最常使用的选项,也是最便于携带的选项。我不知道那些神秘的“相当复杂”是什么。它是相当切割和干燥的。使用
    选择
    时,不需要将插座设置为非阻塞模式。只需使用
    选择
    ,并短暂超时(比如200秒)。当
    select
    返回时,检查状态变量以查看是否应该停止。只有在套接字有数据的情况下才调用
    recv
    。如果你不想让它阻塞,那么使用阻塞函数是毫无意义的…@Olaf我确实想让它阻塞,我只想让它退出阻塞状态,这样我就可以在关闭应用程序时终止线程。@Trevor:那么你显然不想让它阻塞!或者你在图书馆里看到一些神奇的“解锁”电话?这些库只提供基本功能是有原因的。这就是为什么它们被称为“低级”库。您仍然没有解释
    select
    等的实际问题是什么(在Linux上,您可以使用
    poll
    /
    epoll
    ,但Windows总是不那么现代。选项#3是最常使用的选项,也是最可移植的选项。我不知道那些神秘的“相当复杂”是什么是的。它非常干燥。使用
    select
    时,您不需要将插座设置为非阻塞模式。只需使用
    select
    并短暂超时(比如200秒)。当
    select
    返回时,检查状态变量以查看是否应该停止。仅在套接字有数据时调用
    recv
    。如果不想阻止,则使用阻止函数是毫无意义的…@Olaf我确实想阻止它,我只想让它退出其阻止状态,以便终止t关闭我的应用程序时,请执行线程。@Trevor:那么你显然不希望它被阻止!或者你在库中看到了一些神奇的“取消阻止”调用吗?这些库只提供基本功能是有原因的。这就是为什么它们被称为“低级”的原因库。您仍然没有解释
    select
    等的实际问题是什么(在Linux上,您可以使用
    poll
    /
    epoll
    ,但Windows总是不那么现代。不会取消SynchronousIO()工作?@HarryJohnston我不知道。我没有试过,也没有记录它是否与套接字API一起工作。是否取消SynchronousIO()工作?@HarryJohnston我不知道。我没有试过,也没有记录它是否与套接字API一起工作。