如何防止HttpWebRequest的数据包碎片

时间:2010-02-05 07:11:36

标签: .net sockets httpwebrequest fragmentation

我在针对嵌入式设备上的HTTP守护程序使用HttpWebRequest时遇到问题。问题似乎是在写入套接字流的http标头与http有效负载(POST)之间存在足够的延迟,即套接字将套接字缓冲区中的内容释放到服务器。这导致HTTP请求被分割为两个数据包(碎片)。

当然,这是完全有效的,但是如果数据包被分割超过大约1.8ms,则另一端的服务器不能处理它。所以我想知道是否有任何现实的方法来控制它(在客户端上)。

在HttpWebRequest上似乎没有任何属性可以对用于发送的套接字进行这种级别的控制,并且看起来无法访问套接字本身(即通过反射),因为它只在发送,然后发布(作为出站http连接池的一部分)。 BufferWriteStream属性只缓冲webrequest中的正文内容(因此它仍可用于重定向等...),并且似乎不会影响整个请求写入套接字的方式。

那该怎么办?

(我真的试图避免从套接字重新编写HTTP客户端)

一个选项可能是编写HttpWebRequest发送到的某种代理(可能通过ServicePoint),并在该实现缓冲区中写入整个TCP请求。但这似乎是一项艰苦的工作。

当我运行Fidder时也会正常工作(出于同样的原因)但在我们的生产环境中这不是一个真正的选择......

[ps:我知道它确实是碎片数据包之间的间隔问题,因为我敲了一个套接字级别的测试,我使用NoDelay套接字明确控制了碎片]

4 个答案:

答案 0 :(得分:2)

最终,供应商推出了包含新版HTTPD的固件升级,问题就消失了。他们使用的是BusyBox linux,显然他们遇到了HTTPD实现的其他问题。

就我原来的问题而言,除了编写套接字代理之外,我认为没有任何可靠的方法。我上面使用的一些解决方法是运气而不是设计(因为它们意味着.net一次性发送整个数据包)。

答案 1 :(得分:1)

似乎修复它的是在与该URI关联的ServicePoint上禁用Nagling,并将请求作为HTTP 1.0发送(它们本身似乎都没有修复它):

var servicePoint = ServicePointManager.FindServicePoint(uri.Uri);
servicePoint.UseNagleAlgorithm = false;

然而,这似乎仍然只是通过使请求更快地解决它而不是强制将头和有效负载写为一个数据包来修复它。所以它可能在加载的机器/高延迟链路等上失败。

想知道编写碎片整理代理有多难......

答案 2 :(得分:0)

您的嵌入式服务器是否为HTTP / 1.1服务器?如果是这样,请在调用GetRequestStream()之前尝试在webrequest上设置Expect100Continue = false。这将确保HTTP堆栈在发送实体主体之前不期望来自服务器的“HTTP / 1.1 100 continue”报头响应。因此,即使数据包仍然在报头和主体之间分开,数据包间隙也会缩短。

答案 3 :(得分:0)

只是看看客户端分裂数据包问题,我发布了一个与我自己的问题相关的答案:

我在这里看到了答案:

http://us.generation-nt.com/answer/too-packets-httpwebrequest-help-23298102.html