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