如何中断正在等待recv函数的线程?

时间:2011-03-02 13:51:07

标签: c++ sockets

我有一个挂起在recv函数上的套接字监听器:

size_t recvLen = recv(sock, buf, 512, 0);

我想通过打断它来终止这个线程。 MSDN说:

  

发出阻止Winsock调用时   比如recv,Winsock可能需要等待   对于呼叫前的网络事件   可以完成。 Winsock执行   在这种情况下警惕等待,   这可以被一个人打断   异步过程调用(APC)   安排在同一个线程上。

我该怎么做?

6 个答案:

答案 0 :(得分:9)

您可以通过QueueUserAPC将APC排入中断来中断它。但是,在APC中终止线程很可能是不安全的。排队APC不会结束recv,它只会中断它;一旦APC返回,它将再次等待recv

如果要完全停止recv,则应使用select超时,等待数据可用。然后,您可以检查是否应该继续等待数据,或者在每次超时时继续。

答案 1 :(得分:3)

如果您不想再接收任何数据,可以随时终止套接字。只需在其上调用close(),相关函数将立即返回错误。

我过去所做的只是运行另一个超时的线程,等待一段时间后,如果没有设置“不死”标志就杀掉套接字。

答案 2 :(得分:1)

recv之前检查套接字缓冲区更灵活,而不是为select()支持覆盖很多,我想。您可以调用ioctlsocket(SockHandle, FIONREAD, Longint(CountInBuffer))来查看网络缓冲区中是否有数据要读取,然后调用recv(SockHandle, buff, CountInBuffer, 0)。这样,如果使用CountInBuffer足够分配buff本身,则可以进行单次recv调用以读取整个网络读取缓冲区。否则,您需要在循环中调用recv来读取网络缓冲区,这是传统方式。在这两种情况下,您仍处于CountInBuffer

的约束中

答案 3 :(得分:0)

我认为处理这个问题的最好方法是将套接字置于非阻塞I / O模式,这样线程就永远不会阻塞在recv()内部(或者在send()中)。该线程应该只阻塞select()(或WaitMultipleObjects())。这样,如果数据到达套接字,select()(或WaitMultipleObjects())调用将返回(在这种情况下,您可以调用recv()来获取新数据而不会阻塞),但您也可以使用select()/当其他事情发生时,WaitMultipleObjects()返回;例如当它从主线程获得提示时。如果你使用select(),那个提示可以是在另一个套接字对上发送一个字节的主线程(主线程保持套接字对的一端,而I / O线程保持另一端);如果您正在使用WaitMultipleObjects(),那么我相信您可以使用任何会导致WaitMultipleObjects()返回的标准Windows事件/信号方法。

答案 4 :(得分:-1)

Errrr ...在同一个线程上执行APC? : - ))

但是,说真的,目前还不清楚你的目标是什么 如果您只想结束线程,请使用TerminateThread功能 如果要中断此特定呼叫,可以关闭套接字。

答案 5 :(得分:-1)

真正中断阻塞recv()调用并使其完全退出的唯一方法是从另一个线程上下文关闭套接字而不是被阻塞的线程。如果这不是一个选项,那么您需要重新编写套接字逻辑。最好使用非阻塞或异步I / O,这种方式recv()(或后者的WSARecv())永远不会阻塞,你可以做任何你需要做的事情(比如检查线程终止条件) )阅读是在后台进行的。