我们有一个客户和服务器应用程序当前在同一Windows 7 64位计算机上测试。它们都用C#编写,并使用P/Invoke来召集Winsock2库。

该应用程序的整体运行良好,没有任何错误。以及TCP/IP上每个“跳跃”的延迟平均值约为350微秒。

但是,有时在接收数据包之前,有很长的延误超过40至50ms,然后突然它们都会到达。

到目前为止诊断的努力:

  1. 在这些接收数据的延迟期间,服务器继续记录它正在发送数据包。它设置为每1 ms发送一次测试数据包,该测试包将在15或20中进行,有时在客户收到任何一个之前,有时会多达50毫秒。

  2. TCPDUMP用于嗅探回环适配器上的数据包,并表明在此滞后期间,服务器端口(6488)到客户端端口(61743)都有流量。

  3. 客户端调用select()winsock2调用循环中,以便在select()调用之前通过计数器记录其具有正确的文件描述符。当然,这在延迟之前和之后都可以正常工作。

  4. Select()调用后立即进一步登录表明FD不存在 - 要求插座上的读取将阻止。但是,在带有任何延迟的传输期间,日志记录显示其正常工作,因此Select()返回插座的FD进行非阻滞读取。

简而言之,回环适配器似乎将这些数据包放在某个地方很长时间,然后最终将它们运送到接收方。

还有进一步的想法还是解决方案?

有些想法是,通常声称重叠的I/O在Windows上的工作效果更好,但是如果您需要听超过64个插座,这似乎对可伸缩性很重要。

可以切换到重叠会解决问题吗?我们要避免,因为这将增加项目截止日期和预算。这应该适用于select()很好。

另外,是否可以在Windows中处理环回的过程或线程进行上下文切换或其他内容,如果是这样,是否可以将其配置为避免这些延迟?

编辑:正确的答案是确保已禁用Nagle算法。我们认为它是禁用的,但这就是发现错误的地方 - 在我们的内部实现setSocketOption()的内部实现中,我们使用getsocketOption()来验证。因此,事实证明,您必须在连接或绑定套接字之前设置Nodelay,否则它会默默地没有产生任何效果。

非常感谢Fun Mun Pieng的正确答案!!!

有帮助吗?

解决方案

我怀疑这可能是由于 Nagle算法. 。以下代码禁用它:

socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top