如何强制我的C#应用​​程序毫不拖延地确认TCP数据报?

时间:2011-04-28 21:10:46

标签: .net tcp tcpclient

我尝试使用TcpClient.NoDelay = true,但它仍然不会在200毫秒后发回确认。我更改了网络适配器的Windows注册表设置以禁用Nagle算法,并且有效,ACK立即发送。不应该有办法在不更改注册表设置的情况下禁用200毫秒的延迟吗?

更新:感谢有关UDP的建议。我同意UDP是应用程序的正确协议,但不幸的是我正在处理一个目前只有TCP接口的设备,因此我的双手被绑在那里。

3 个答案:

答案 0 :(得分:2)

ACK数据包是底层操作系统的TCP / IP堆栈内部工作的问题。您的应用程序不应该受到TCP协议的标准行为的任何损害。如果是,您应该考虑使用其他类似UDP。

答案 1 :(得分:1)

NoDelay不会按照您的想法执行操作。它禁用Nagle算法,这是一种优化,如果完整数据包尚未排队发送以减少发送的数据包,则会等待一小段时间。它与确认无关。

如果要无延迟地发送数据包,请使用UDP。 TCP必须等待确认是否必须重新发送数据包,这是一种防止缓冲区溢出和丢失数据的安全机制。

编辑:

重新阅读您的问题后,您的问题似乎有点误导。如果在适配器中禁用nagle工作,那么这意味着您的问题是数据包不是立即 SENT ,而不是确认不会立即返回。 ack马上回来,只是发送的延迟是问题。

您是在打开套接字之后还是之前设置了NoDelay选项?您是否在设置NoDelay后检查NoDelay的状态以确保它已设置?将其设置为true可能会失败,在这种情况下,即使在您设置它之后它仍然是假的。

答案 2 :(得分:1)

我知道这是一个老问题,但是我刚刚找到了它,而我完全同意以下说法: “ ACK数据包是底层操作系统的TCP / IP堆栈的内部工作问题。”

我完全不同意以下说法: “您的应用程序不应受到TCP协议的标准行为的任何损害。”

如果那是真的! TCP套接字的默认行为不是关闭TCP_NODELAY,也关闭TCP_QUICKACK吗? AFAIK在我开发的所有平台上都是如此,如果我记错了,请纠正我。

考虑客户端将服务请求分解为多个小数据包的情况。服务器将在第一个数据包之后等待更多的时间,然后再确认,因为禁用了快速确认,并且认为等待将是一种优化。 “肯定还会来的,对吗?我将在它们到达后立即一次确认多个数据包!”。但是客户端在发送更多消息之前正在等待ACK,因为禁用了minigramgram预防(又名nagle的算法),并且下一个数据包远低于最大有效负载。因此,是否损害应用程序取决于应用程序的性质,但是肯定某些应用程序会因为产生额外的RTT延迟而受到损害。应用程序层没有与网络层完美分离。现在,假设有问题的应用程序正在发出HTTP请求。当然,您可以说它不应拆分其请求,但这样做并非无效,并且底层网络层现在正在给您造成伤害。在这种情况下,也不是完全切换到UDP的选项。此外,除了有点搞笑之外,某些UDP库还实现了自己的版本的小报保护,并默认启用了它(例如RakNet)。

最后,很抱歉,我没有足够的代表对此作出评论,所以这是一个答案:'(但是,由于这是答案,所以我的实际回答是检查您是否可以通过等效于Winsock的setSockopt的C#启用快速确认。如果可以的话,一定要在客户端和服务器上执行此操作,如果没有及时接收到ACK,则是一个问题。当然,无论大小如何,您都必须为每个负载增加TCP / IP标头开销。最后,请始终使用数据包嗅探器来查看到底发生了什么,以便您仅尝试修复已损坏的问题。

参考: John Nagle对我上面概述的问题的回答 https://news.ycombinator.com/item?id=10607422