closesocket()没有完成IOCP的待处理操作

时间:2017-10-12 06:44:22

标签: c++ sockets winsock iocp closesocket

我目前正在使用C ++编写服务器应用程序。我的主要灵感来自以下例子:

Windows SDK IOCP Excample

The I/O Completion Port IPv4/IPv6 Server Program Example

我的应用程序非常类似于这些(socketobj,packageobj,...)。

一般情况下,我的应用运行没有问题。唯一让我烦恼的事情是半开放的连接。

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

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

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

我做错了什么?其他人也有遇到同样的状况吗? MSDN文档错了吗?有哪些替代方案?

我正在考虑"徘徊"功能,或使用CancelIoEx()功能

明确取消每个操作

修改 (感谢您的回复)

昨天晚上,我为每个sockedobj添加了一个链式列表,用于保存待处理操作的每个对象。有了这个,我尝试了CancelIOEx()函数。对于大多数操作,函数返回0并且GetLastError()返回 ERROR_NOT_FOUND

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

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

尽快跟踪代码。

1 个答案:

答案 0 :(得分:0)

  • '逗留'设置可用于重置连接,但这样你将(a)丢失数据和(b)向对等体发送重置,这可能会使其受到恐吓。
  • 如果你想到一个积极的徘徊超时,它并没有真正的帮助。
  • 关闭读取应该终止读取操作,但是只有写入才会在挂起写入后排队,所以它根本没有帮助。
  • 如果挂起的写入是问题,而没有完成,则必须取消它们。