一些使用WSASend的OVERLAPS没有使用GetQueuedCompletionStatus及时返回?

时间:2009-07-17 19:30:29

标签: c++ windows iocp

背景:我正在使用CreateIoCompletionPort,WSASend / Recv和GetQueuedCompletionStatus在我的服务器上执行重叠的套接字io。对于流控制,当发送到客户端时,我只允许在所有挂起的OVERLAP从IOCP弹出时调用多个WSASend()。

问题:最近,当OVERLAP没有返回IOCP时会出现这种情况。调用GetQueuedCompletionStatus的线程不会获取它们,它们仍保留在我的本地挂起队列中。我已经验证客户端是否从套接字接收数据并且套接字已连接。调用WSASend()时没有返回任何错误。如果没有像以下那样的外部刺激,OVERLAP就会“永远”回来:

  1. 断开套接字与客户端或服务器的连接,立即允许GetQueuedCompletionStatus线程检索OVERLAP
  2. 在所有OVERLAP突然从队列中弹出之前,对WSASend()进行额外调用,有时需要多次调用。
  3. 问题:有没有人见过这种行为?关于是什么导致这个的任何想法?

    谢谢, 杰弗里

1 个答案:

答案 0 :(得分:4)

如果TCP窗口已满,

WSASend()可能无法及时完成。在这种情况下,堆栈不能再发送任何数据,因此WSASend()等待,直到TCP堆栈CAN发送更多数据才会完成。

如果您的客户端和服务器之间没有协议本身没有内置流量控制的协议,并且您没有根据写入完成情况自行执行任何流量控制,并且只是以您的服务器可以快速发送数据发送然后你可能会到达网络或你的客户端无法跟上并且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