closesocket()未完成IOCP的挂起操作

closesocket() not completing pending operations of IOCP

本文关键字:挂起 操作 IOCP 未完成 closesocket      更新时间:2023-10-16

我目前正在C++中开发一个服务器应用程序。我的主要灵感来自这些例子:

Windows SDK IOCP Excample

I/O完成端口IPv4/IPv6服务器程序示例

我的应用程序与这些非常相似(socketobj,packageobj,…)。

总的来说,我的应用程序运行时没有问题。唯一仍然给我带来麻烦的是半开放的关系。

我的策略是:我在一段时间内检查每个连接的客户端,并向上计数一个"空闲计数器"。如果出现一个完成,我会重置此计时器。如果Idle计数器过高,我会设置一个布尔值以防止其他线程发布操作,然后调用closesocket()

我的假设是,现在套接字已关闭,挂起的操作将完成(可能不是立即完成,而是在一段时间后完成)。这也是MSDN文档描述的行为(提示,第二段)。我需要这个,因为只有在所有操作完成后,我才能释放资源。

长话短说:我的情况并非如此。我用我的testclient应用程序进行了一些测试,并进行了一些cout和断点调试,发现关闭套接字的挂起操作没有完成(即使在等待10分钟后)。在closesocket()之前,我也已经尝试过shutdown()调用,两者都没有返回错误。

我做错了什么?这种情况发生在其他人身上吗?MSDN文档有错吗?有哪些替代方案?

我目前正在考虑"延迟"功能,或者使用CancelIoEx()功能明确取消每个操作

编辑: (感谢您的回复)

昨天晚上,我为每个sockedobj添加了一个链表,以保存挂起操作的per-io-obj。有了这个,我尝试了CancelIOEx()函数。对于大多数操作,函数返回0,GetLastError()返回ERROR_NOT_FOUND

在这种情况下,释放每个Io对象是否安全?

我还发现,当我在同一台机器上运行服务器应用程序和客户端应用程序时,这种情况更频繁。服务器无法完成写入操作的情况时有发生。我认为发生这种情况是因为客户端接收缓冲区已满。(客户端不会停止接收数据!)。

剪下的代码如下尽快。

  • "linger"设置可以用于重置连接,但这样一来,您将(a)丢失数据,(b)向对等方发送重置,这可能会让对等方感到害怕
  • 如果你正在考虑一个积极的延迟超时,这并没有真正的帮助
  • 为读取而关闭应该会终止读取操作,但为写入而关闭只会在挂起的写入之后排队,因此根本没有帮助
  • 如果挂起的写入是问题,并且没有完成,则必须取消它们