我在Windows中使用多线程IOCP服务器。为了避免处理许多未决的读取,每个连接的套接字上始终只有一个wsarecv
操作。简而言之,我的设计如下:
客户端连接后的
wsarecv
发布在已连接的套接字wsarecv
时,处理数据并将wsasend
发布在同一套接字wsasend
完成(GQCS收到通知)时,再次发布wsarecv
。 这意味着在第2步和第3步之间只有很少的时间,这时没有等待客户数据的未决wsarecv等待任何时间出现。
是这种情况,我应该担心还是可以假设,如果数据将在此特定的少量时间内到达,则将其存储在某种内部缓冲区中,并在发布步骤3的
wsarecv
时从中取走?寻求帮助。
最佳答案
只要您尚未禁用网络堆栈的缓冲(使用SO_RCVBUF
并将缓冲区大小设置为0),您就将在网络堆栈中保留一些缓冲区空间,如果没有WSARecv()
待处理,将使用该缓冲区空间。
如果您使用的是TCP,那么您在填充此缓冲区空间时甚至不必担心,因为这将导致零窗口,并且发送方有望停止发送(请参阅here,了解为什么它可能实际上并未停止发送),但是即使不是这样,您的堆栈也只会丢弃后续的数据报,而TCP最终会重新发送它们。
与UDP有点不同。如果填充了recv缓冲区,则将开始删除数据报。默认情况下,堆栈将丢弃最新的数据报,您可以通过设置SIO_ENABLE_CIRCULAR_QUEUEING
来更改它,这将导致丢弃最旧的数据报。
您可以通过以下方式始终选择在连接上始终保留至少一个WSARecv()
:a)发布多个,然后b)发布新的WSARecv()
作为完成时的第一件事。这对于UDP效果很好,但是对于TCP,这种方法的问题是您必须考虑到多个recv可以“同时”完成的事实,然后必须确保I/O线程协同工作以保持同步TCP数据流(有关问题,请参见here)。
禁用堆栈的recv缓冲区并在连接上始终有足够的ojit_code挂起可能会更有效,因为这将从入站数据路径中删除内存拷贝。
关于c++ - 当前没有wsarecv时,传入数据会发生什么情况,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22720924/