2014-03-28 48 views
1

我在Windows中使用多线程IOCP服务器。为了避免处理很多未决的读取,我在每个连接的套接字上始终只有一个wsarecv操作。总之我的设计是这样的:当没有wsarecv时,输入数据会发生什么

  1. 客户端连接后,wsarecv是在连接插座贴
  2. 在执行wsarecv,数据处理连线和wsasend张贴在同一插座上
  3. wsasend从第2步完成(GQCS获得通知),wsarecv重新贴。

这意味着在步骤2和步骤3之间只有一小段时间,当没有挂起的wsarecv正在等待客户端数据时,它可以在任何时候出现。

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

thx寻求帮助。

+2

TCP或UDP?在任何一种情况下,它都会被缓冲,在UDP的情况下,如果缓冲时间过长(随着更多数据的进入),它可能会被丢弃。 – Chad

+0

@乍得,它是TCP。 – maciekm

+0

@maciekm考虑在标题,文本和标签中添加它的tcp信息 –

回答

2

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

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

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

您可以选择始终至少有一个WSARecv()等待在连接上通过a)张贴多个开始和b)发布一个新的作为您完成时的第一件事。这适用于UDP,但对于TCP而言,这种方法的问题在于,您必须考虑到多个recvs可能“同时”完成,然后您必须确保您的I/O线程一起工作以保持TCP数据流同步(有关问题,请参阅here)。

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

相关问题