如何中止winsock阻塞调用?

Posted

技术标签:

【中文标题】如何中止winsock阻塞调用?【英文标题】:How to abort winsock blocking call? 【发布时间】:2010-01-25 10:14:31 【问题描述】:

我在 C++ 中使用 Winsock 2,想知道如何让我的服务器停止从客户端连接读取。阅读线程在recv() 中被阻塞,我不知道如何中止它。一种方法是使用带有select() 的非阻塞套接字,但该线程必须等待才能检查新的select()

停止读取套接字的正确方法是什么?

【问题讨论】:

关闭套接字进行读取。这将导致接收解除阻塞并返回零,并且它应该已经被编程为关闭套接字并停止读取并在发生这种情况时退出线程。 【参考方案1】:

要中止对recv() 的阻塞调用,您可以使用来自另一个 线程的closesocket() 关闭套接字。即使它有点难看,它应该可以工作。

您也可以尝试shutdown() 套接字(我从未测试过)。

【讨论】:

你知道recv在调用closesocket的时候已经启动了吗?如果不是怎么办? @curiousguy:我同意你的担忧。根据"Remarks" section of the Microsoft documentation on the closesocket() function,在调用 closesocket 后,套接字描述符可以立即被重用。因此,这可能会引入race condition。根据 Microsoft 文档,closesocket() 因此永远不应与同一个套接字上的另一个 Winsock 函数调用同时调用。 这实际上是不可能做到的。正如好奇的人指出的那样,您无法确保closesocket 出现在对recv 的调用之后,如果调用以其他顺序执行,结果可能完全无法预测。如果可以的话,我会对这个答案投三票。【参考方案2】:

如果您的程序除了使用套接字 I/O 之外还有其他事情要做,那么您首先不应该阻塞。

您声称您的线程必须等待,但这只是您程序当前设计的反映。您应该重新设计它,使其适用于某种形式的非阻塞套接字。每个网络问题都可以使用非阻塞套接字来解决。

由于您使用的是 Winsock,因此这里有 many alternatives,而不仅仅是 select()select() 是一个不错的选择,仅当您的应用程序必须在多个平台上运行并且您无法使用每个现代平台上可用的高级(但相互不兼容)替代方案时。

【讨论】:

以上是关于如何中止winsock阻塞调用?的主要内容,如果未能解决你的问题,请参考以下文章

在winsock中,我将如何阻止接受函数从另一个线程阻塞?

Select模型

在 MFC 中使用异步过程调用中断接受 winsock 调用

Winsock recv() 不阻塞

在winsock2中使用选择

阻塞与非阻塞winsock的速度/性能特征