c++ - 当当前没有 wsarecv 时,传入数据会发生什么情况

标签 c++ sockets winsock iocp

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

  1. 客户端连接后,wsarecv发布在已连接的套接字上
  2. wsarecv被执行,数据被处理并且 wsasend发布在同一个套接字上
  3. 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/

相关文章:

c++ - 如何在 Windows 上设置 UDP 源地址

c++ - winsock 缺失数据 c++ win32

c++ - 从主函数调用事件

c++ 为什么我的日期解析不是线程安全的?

java - 在 Java 中停止阻塞套接字

python-3.x - 如何使用 python 套接字 AF_bluetooth 套接字广播蓝牙查询?

具有多个客户端的 C++ Winsock 服务器?

c++ - Qt如何连接rubberBandChanged信号

c++ - boost::spirit::qi::phrase_parse 某处的未定义行为

javascript - Socket.io 触发两个 node.js 应用程序之间的事件?