当完成数据包可用时,如何防止I / O完成端口阻塞?

Charunnera

我有一个服务器应用程序,该应用程序使用Microsoft的I / O完成端口(IOCP)机制来管理异步网络套接字通信。总的来说,这种IOCP方法在我的环境中表现良好。但是,我遇到了一个极端情况,我正在寻求指导:

为了进行测试,我的服务器应用程序正在通过千兆位LAN将数据流(例如,约400 KB /秒)传输到单个客户端。一切都很好...直到我从局域网断开客户端的以太网电缆。以这种方式断开电缆连接可防止服务器立即检测到客户端已消失(即,客户端的TCP网络堆栈不会向服务器发送连接终止的通知)

同时,服务器继续对WSASend客户端进行调用……并且由于这些调用是异步的,因此它们似乎“成功”(即,数据由OS缓冲在套接字的出站队列中)。

当这一切发生时,我有16个线程被阻塞GetQueuedCompletionStatus,等待在端口可用时从端口检索完成数据包。在断开客户端电缆之前,有恒定的完成数据包流。现在,一切(按预期)似乎都停止了……大约32秒钟。32秒后,IOCP跳回动作,返回FALSE非空lpOverlapped值。GetLastError返回121(信号灯超时时间已到期。)我只能假设错误121是WSASend在TCP堆栈确定客户端消失后最终超时的产物。

网络堆栈需要32秒才能确定我的客户端不可用,所以我很好。问题是,当系统做出此决定时,我的IOCP瘫痪了。例如,WSAAccept发布到同一IOCP的事件在接收GetQueuedCompletionStatus到失败的完成数据包(指示错误121)之前,不会被阻塞的16个线程中的任何一个处理

解决此问题的最初计划涉及WSAWaitForMultipleEvents在致电后立即使用WSASend如果未在(例如3秒)内发出套接字事件信号,那么我将终止套接字连接并继续进行(以防止对IOCP产生广泛的阻塞影响)。不幸的是,WSAWaitForMultipleEvents似乎从未遇到过超时(因此异步套接字可能是通过异步来发信号的吗?或者将数据复制到TCP队列中是否有资格发出信号?)

我仍在尝试解决所有问题,但希望有人对如何防止IOCP挂起有所了解。

其他详细信息:我的服务器应用程序在具有8个内核的Win7上运行;IOCP配置为最多使用8个并发线程。我的线程池有16个线程。大量的RAM,处理器和带宽。

在此先感谢您的建议。

伦·霍尔盖特

WSASend()在这种情况下完井通常会停顿。在TCP堆栈超时并重新发送尝试并完成所有未完成的错误发送之前,您不会得到它们。这不会阻止任何其他操作。我希望您要么测试不正确,要么代码中有错误。

请注意,您的“修复”有缺陷。如果发件人发送的速度快于使用者可以消耗的速度,则在正常连接期间的任何时候都可能会看到这种“延迟的发送完成”情况。有关TCP流控制和异步写入的信息,请参见本文更好的计划是对要允许的大量写操作(每个连接)使用一个计数器,如果达到该计数器,则停止发送,然后在该计数器降至“低水位线”阈值以下时恢复发送。

请注意,如果您已将网络电缆拔出机器,您如何期望其他操作完成?读只会坐在那里,只有在写入失败后才会失败,AcceptEx只会坐在那里,等待条件纠正。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章