8

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

当然,这是完全有效的,但是如果数据包的拆分时间超过 1.8 毫秒,另一端的服务器将无法处理。所以我想知道是否有任何现实的方法来控制这个(在客户端)。

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

那么该怎么办?

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

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

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

[ps:我知道这肯定是碎片数据包之间的间隔问题,因为我敲开了一个套接字级别的测试,在那里我使用 NoDelay 套接字显式控制了碎片]

4

4 回答 4

2

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

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

于 2011-03-24T09:05:36.627 回答
1

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

于 2010-02-05T14:21:12.470 回答
1

似乎已经解决的问题是禁用与该 URI 关联的 ServicePoint 上的 Nagling,并将请求作为 HTTP 1.0 发送(它们自己似乎都无法修复它):

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

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

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

于 2010-02-08T00:25:44.013 回答
0

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

我在这里看到了答案:

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

于 2012-11-13T16:50:41.470 回答