HttpWebRequest的是分块的数据慢的是、数据、HttpWebRequest

2023-09-03 06:08:21 作者:韶华倾覆三生梦

我使用的HttpWebRequest连接到我的内部内置的HTTP服务器。我的问题是,它比通过连接到服务器例如邮差慢很多(https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm?hl=en),这可能是使用Chrome浏览器内置的功能来请求数据。

I'm using HttpWebRequest to connect to my in-house built HTTP server. My problem is that it is a lot slower than connecting to the server via for instance PostMan (https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm?hl=en), which is probably using the built-in functions in Chrome to request data.

服务器使用这个例子MSDN( HTTP上建:// MSDN。 microsoft.com/en-us/library/dxkwh6zw.aspx 的),并使用64的缓冲大小的请求是与体内一些数据的HTTP请求。​​

The server is built using this example on MSDN (http://msdn.microsoft.com/en-us/library/dxkwh6zw.aspx) and uses a buffer size of 64. The request is a HTTP request with some data in the body.

当通过邮递员连接,该请求被分成一串块和BeginRecieve()被调用多次,每次接收64B和服用大约2毫秒。除了最后一个,这比64B收到较少。

When connecting via PostMan, the request is split into a bunch of chunks and BeginRecieve() is called multiple times, each time receiving 64B and taking about 2 milliseconds. Except the last one, which receives less than 64B.

但随着我的客户端连接使用HttpWebRequest的时候,第一个BeginRecieve()回调接收64B,需时约1毫秒,以下只接收47B和需要近200毫秒,最后是第三个接收关于58B和需要2ms的。

But when connecting with my client using HttpWebRequest, the first BeginRecieve() callback receives 64B and takes about 1 ms, the following receives only 47B and takes almost 200 ms, and finally the third receives about 58B and takes 2ms.

什么是与第二BeginRecieve?我注意到连接,只要我开始写数据到HttpWebRequest的输入流建立,但数据接收没有启动,直到我打电话的GetResponse()。

What is up with the second BeginRecieve? I note that the connection is established as soon as I start to write data to the HttpWebRequest input stream, but the data reception does not start until I call GetResponse().

下面是我的HttpWebRequest code:

Here is my HttpWebRequest code:

var request = (HttpWebRequest)WebRequest.Create(url);

request.Method = verb;
request.Timeout = timeout;
request.Proxy = null;
request.KeepAlive = false;
request.Headers.Add("Content-Encoding", "UTF-8");
System.Net.ServicePointManager.Expect100Continue = false;
request.ServicePoint.Expect100Continue = false;

if ((verb == "POST" || verb == "PUT") && !String.IsNullOrEmpty(data))
{
    var dataBytes = Encoding.UTF8.GetBytes(data);

    try
    {
        var dataStream = request.GetRequestStream();
        dataStream.Write(dataBytes, 0, dataBytes.Length);
        dataStream.Close();
    }
    catch (Exception ex)
    {
        throw;
    }

}

WebResponse response = null;
try
{
    response = request.GetResponse();
}
catch (Exception ex)
{
    throw;
}

var responseReader = new StreamReader(rStream, Encoding.UTF8);
var responseStr = responseReader.ReadToEnd();

responseReader.Close();
response.Close();

我是什么做错了吗?为什么表现这么多不同的方式从Web浏览器一个HTTP请求?这实际上是将延迟200毫秒到我的应用程序。

What am I doing wrong? Why is it behaving so much differently than a HTTP request from a web browser? This is effectively adding 200ms of lag to my application.

推荐答案

这看起来像的 Nagle算法与 TCP延迟确认冲突。在你的情况你是(根据你的号码〜170字节)发送一个小的HTTP请求。这很可能比该MSS(最大段大小)意味着Nagle算法将在之后更小。服务器可能延迟造成的高达500毫秒的延迟ACK中。详情请参见链接。

This looks like a typical case of the Nagle algorithm clashing with TCP Delayed Acknowledgement. In your case you are sending a small Http Request (~170 bytes according to your numbers). This is likely less than the MSS (Maximum Segment Size) meaning that the Nagle Algorithm will kick in. The server is probably delaying the ACK resulting in a delay of up to 500 ms. See links for details.

您可以通过 ServicePointManager.UseNagleAlgorithm = FALSE (前发出的第一个请求),请参阅 MSDN 。

You can disable Nagle via ServicePointManager.UseNagleAlgorithm = false (before issuing the first request), see MSDN.

另请参见 Nagle算法是不友善对小的要求进行了详细的讨论,包括Wireshark的分析。

Also see Nagle’s Algorithm is Not Friendly towards Small Requests for a detailed discussion including a Wireshark analysis.

请注意:在你的答案,你正在运行到同样的情况,当你写的读写。当您切换到写 - 读你解决这个问题。不过,我不相信你可以指示HttpWebRequest的(或HttpClient的为此事)送小请求作为一个TCP写操作。这很可能会在某些情况下获得良好的优化。 Althought它可能会导致一些附加的阵列复制,产生不利影响的性能。

Note: In your answer you are running into the same situation when you do write-write-read. When you switch to write-read you overcome this problem. However I do not believe you can instruct the HttpWebRequest (or HttpClient for that matter) to send small requests as a single TCP write operation. That would probably be a good optimization in some cases. Althought it may lead to some additional array copying, affecting performance negatively.