当没有wsarecv时,传入数据会发生什么

时间:2014-03-28 18:51:52

标签: c++ sockets winsock iocp

我在windows中处理多线程IOCP服务器。为了避免处理许多挂起的读取,我在每个连接的套接字上始终只有一个wsarecv操作。简而言之,我的设计如下:

  1. 客户端连接后,wsarecv发布在已连接的套接字
  2. 执行wsarecv时,数据被处理,wsasend张贴在同一个套接字上
  3. 当第2步中的wsasend完成时(GQCS收到通知),wsarecv会再次发布。
  4. 这意味着在步骤2和3之间有一段时间,当没有待处理的wsarecv等待客户端数据时,可以随时出现。

    这种情况,我应该担心,或者我可以假设如果数据在这个特定的时间内到达,它将存储在某种内部缓冲区中,并在wsarecv时从中获取从第3步发布?

    请求帮助。

1 个答案:

答案 0 :(得分:2)

只要您没有禁用网络堆栈的缓冲(使用SO_RCVBUF并将缓冲区大小设置为0),那么您将在网络堆栈中有一些缓冲区空间,如果你没有WSARecv()待定。

如果您正在使用TCP,那么当您填充此缓冲区空间时甚至不必担心,因为这将导致零窗口,并且发送方将希望停止发送(请参阅here了解原因它可能实际上并没有停止发送),但即使它没有,那么你的堆栈只会丢弃后续的数据报,TCP最终会重新发送它们。

使用UDP它有点不同。如果填充recv缓冲区,则会开始删除数据报。默认情况下,堆栈将删除最新的数据报,您可以通过设置SIO_ENABLE_CIRCULAR_QUEUEING来更改此值,这将导致最旧的数据报被删除。

您可以选择在连接上始终至少有一个WSARecv()待定a)发布多个以及b)发布新的一个作为您完成时所做的第一件事。这适用于UDP,但对于TCP,这种方法的问题在于,您必须考虑到多个recv可以同时完成的事实"然后你必须确保你的I / O线程协同工作以保持TCP数据流同步(请参阅here了解问题)。

禁用堆栈的recv缓冲区并且在连接上始终有足够的WSARecv()等待可能更有效,因为这将从入站数据路径中删除内存副本。 / p>