我在windows中处理多线程IOCP服务器。为了避免处理许多挂起的读取,我在每个连接的套接字上始终只有一个wsarecv
操作。简而言之,我的设计如下:
wsarecv
发布在已连接的套接字wsarecv
时,数据被处理,wsasend
张贴在同一个套接字上wsasend
完成时(GQCS收到通知),wsarecv
会再次发布。这意味着在步骤2和3之间有一段时间,当没有待处理的wsarecv等待客户端数据时,可以随时出现。
这种情况,我应该担心,或者我可以假设如果数据在这个特定的时间内到达,它将存储在某种内部缓冲区中,并在wsarecv
时从中获取从第3步发布?
请求帮助。
答案 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>