2011-04-02 21 views
5

背景

我在C#中实现了一个HTTP服务器。 使用ab我发现了一个奇怪的性能问题。 每个请求花费5毫秒时间保持关闭状态,但保持活动时间为40毫秒!通过暂时启用NoDelay来实现套接字“Flush”

将测试页生成为单个字节[],然后使用单个套接字作为回复发送。发送调用。

原因是据我所知,Nagle在TCP协议栈中使用的算法。

TCP Flush?

到目前为止,我在每个HTTP请求服务结束时都使用NoDelay属性。

socket.NoDelay = true; 
socket.NoDelay = false; 

现在确实解决了这个问题。但我没有文档来备份我的发现。

这是在linux/mono系统上测试的。

是否有标准的方法来刷新TCP连接?

相关

This answer是解决同样的问题。这里的区别在于我只想暂时禁用算法。

回答

6

我用Wireshark测试了这个。不幸的是,

socket.NoDelay = true; 
socket.NoDelay = false; 

没有效果。同样,

socket.NoDelay = true; 
socket.Send(new byte[0]); 
socket.NoDelay = false; 

也没有效果。从观察到的行为看来,NoDelay属性似乎只影响下一次调用Send且具有非空缓冲区。换句话说,您必须在NoDelay之前发送一些实际数据才能起作用。

因此,我得出结论,如果您不想发送任何额外的数据,则无法显式刷新套接字。

不过,既然你正在编写一个HTTP服务器,你可以使用一些小技巧:

  • 对于请求正在使用Transfer-Encoding: chunked提供服务,您可以发送端的流标记(在"\r\n0\r\n\r\n")与NoDelay = true
  • 如果您从本地文件系统提供文件,您将知道文件何时结束,因此您可以在发送最后一个块之前设置NoDelay = true
  • 对于使用Content-Encoding: gzip服务的请求,可以在关闭gzip流之前设置NoDelay = true; gzip流将在实际完成和关闭之前发送最后一些位。

我一定要去上面添加到我现在 HTTP服务器:)

+2

如果只有我们有一个[TCP Nagle刷新](http://stackoverflow.com/questions/6726832/what-happened-to-the-tcp-nagle-flush)... – 2011-07-18 13:56:42

+0

难道你是在运行窗口有不同的实现? – hultqvist 2011-07-18 22:13:18

-3

在TCP中没有这样的事情。 TCP是一种基于流的协议,它可以对您的数据进行分组/拆分/连接/分组。通过禁用nagle它只会那么频繁。

不要禁用nagle。

的内格尔TCP/IP算法 设计,以避免与小 包,叫tinygrams,慢 网络问题。该算法表示,一个 TCP/IP连接可以只有一个 尚未确认的尚未完成的小细分区段 。 “小”的定义 各不相同,但通常定义为“小于段 大小”的 ,其在以太网上大约为1500 字节。

在这里看看:Disabling TCP/IP Nagle Algorithm Improves Speed on Slow Nets

+3

究竟为什么我不应该禁用Nagle算法在短期内?它显然给了我8倍的响应时间。 – hultqvist 2011-04-03 11:28:32

+0

相关:[什么发生在TCP Nagle刷新](http://stackoverflow.com/questions/6726832/what-happened-to-the-tcp-nagle-flush)。我想知道这个想法来自TCP flush是没有意义和/或不存在的。 – 2011-07-18 13:05:49

+0

法拉盛对流有意义。并说TCP不支持刷新是误导。 TCP的大多数实现不支持显式刷新其发送缓冲区,但这不是TCP的限制,这是这些实现的限制。有些情况下,在选定的点上避免使用黑色的冲洗会非常有用。 – CodesInChaos 2011-07-18 22:16:20

1

已经写了一个颇为流行的Web服务器自己,我不认为纳格algortihm是你真正的问题。

你如何建立你的回应,你如何发送他们?

+0

我已经更新了我的问题,数据在一次调用中发送到Socket.Send(Byte [] ,,),内容虽然很小,但是却是400字节。 – hultqvist 2011-05-03 21:16:17