使用 WSASend 的一些重叠未使用 GetQueuedCompletionStatus 及时返回?
背景:我正在使用 CreateIoCompletionPort、WSASend/Recv 和 GetQueuedCompletionStatus 在我的服务器上执行重叠套接字 io。 对于流量控制,当发送到客户端时,我只允许在所有挂起的 OVERLAP 已从 IOCP 中弹出时调用多个 WSASend()。
问题:最近,有时会出现 OVERLAP 未返回到 IOCP 的情况。 调用 GetQueuedCompletionStatus 的线程没有获取它们,它们仍保留在我的本地待处理队列中。 我已经验证客户端确实从套接字接收数据并且套接字已连接。 调用 WSASend() 时没有返回任何错误。 如果没有外部刺激,重叠“永远”不会返回,如下所示:
- 断开套接字与客户端或服务器的连接,立即允许 GetQueuedCompletionStatus 线程检索
- 重叠 对 WSASend() 进行额外调用,有时需要多次调用,然后才能执行所有操作重叠突然从队列中弹出。
问:有人见过这种行为吗? 关于造成这种情况的原因有什么想法吗?
谢谢, 杰弗里
Background: I'm using CreateIoCompletionPort, WSASend/Recv, and GetQueuedCompletionStatus to do overlapped socket io on my server. For flow control, when sending to the client, I only allow several WSASend() to be called when all pending OVERLAPs have popped off the IOCP.
Problem: Recently, there are occassions when the OVERLAPs do not get returned to the IOCP. The thread calling GetQueuedCompletionStatus does not get them and they remain in my local pending queue. I've verified that the client DOES receive the data off the socket and the socket is connected. No errors were returned when the WSASend() calls were made. The OVERLAPs simply "never" come back without an external stimulus like the following:
- Disconnecting the socket from the client or server, immediately allows the GetQueuedCompletionStatus thread to retrieve the OVERLAPs
- Making additional calls to WSASend(), sometimes several are needed, before all the OVERLAPs suddenly pop off the queue.
Question: Has anyone seen this type of behavior? Any ideas on what is causing this?
Thanks,
Geoffrey
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果 TCP 窗口已满,
WSASend()
可能无法及时完成。 在这种情况下,堆栈无法发送更多数据,因此您的WSASend()
会等待,并且直到 TCP 堆栈可以发送更多数据后才会完成。如果您的客户端和服务器之间碰巧有一个协议本身没有内置流量控制的协议,并且您自己没有根据写入完成情况进行任何流量控制,而只是以服务器发送的速度发送数据,那么您可能会达到网络或客户端无法跟上并且 TCP 流量控制启动的程度(当 TCP 窗口已满时)。 如果您继续通过额外调用
WSASend()
来异步触发数据,那么最终您将耗尽机器上的所有非分页内存,到那时所有的赌注都会被取消。 (驱动程序很有可能导致盒子蓝屏)。因此,总而言之,重叠套接字写入的完成有时可能需要比您预期更长的时间才能返回。 在您的示例中,我希望关闭套接字时获得的完成全部都是失败?
我在我的博客上对此进行了更多讨论; 这里:http://www.lenholgate.com/ blog/2008/07/write-completion-flow-control.html 和此处:http://www.serverframework.com/asynchronousevents/2011/06/tcp-flow-control-and-asynchronous-writes.html
WSASend()
can fail to complete in a timely manner if the TCP window is full. In this case the stack can't send any more data so yourWSASend()
waits and your completion doesn't occur until the TCP stack CAN send more data.If you happen to have a protocol between your client and server that has no flow control built into the protocol itself AND you aren't doing any flow control yourself based on write completions and are just sending data as fast as your server can send then you may get to a point where either the network or your client can't keep up and TCP flow control kicks in (when the TCP window gets full). If you continue to just fire off data asynchronously with additional calls to
WSASend()
then eventually you'll chew your way through all of the non-paged memory on the machine and at that point all bets are off (chances are high that a driver may cause the box to bluescreen).So, in summary, completions from overlapped socket writes can and will sometimes take longer to come back than you may expect. In your example, I expect that the completions that you get when you close the socket are all failures?
I talk about this some more on my blog; here: http://www.lenholgate.com/blog/2008/07/write-completion-flow-control.html and here: http://www.serverframework.com/asynchronousevents/2011/06/tcp-flow-control-and-asynchronous-writes.html