HttpWebRequest对于分块数据很慢我正在使用HttpWebRequest连接到我在内部构建的HTTP服务器。我的问题是它比通过PostMan(https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm?hl=en)连接到服务器慢很多,后者可能使用内置的-在函数中可以请求数据。服务器是使用MSDN(http://msdn.microsoft.com/en-us/library/dxkwh6zw.aspx)上的这个示例构建的,使用的缓冲区大小为64。request是一个包含一些数据的HTTP请求。当通过PostMan连接时,请求被分成一堆块,并且BeginRecieve()被调用多次,每次接收64B并花费大约2ms??。除了最后一个,收到的不到64B。但是当使用HttpWebRequest连接到我的客户端时,第一个BeginRecieve()回调接收到64B并花费了大约1ms,以下仅接收到47B并花费了大约200ms,最后第三个收到了大约58B并花费了大约2ms??。第二个BeginRecieve有什么用?我注意到,一旦我开始将数据写入HttpWebRequest输入流,连接就建立了,但是数据接收直到我调用GetResponse()才开始。这是我的HttpWebRequest代码:varrequest=(HttpWebRequest)WebRequest.Create(url);request.Method=动词;request.Timeout=超时;请求.Proxy=null;请求.KeepAlive=false;request.Headers.Add("内容编码","UTF-8");System.Net.ServicePointManager.Expect100Continue=false;request.ServicePoint.Expect100Continue=false;if((verb=="POST"||verb=="PUT")&&!String.IsNullOrEmpty(data)){vardataBytes=Encoding.UTF8.GetBytes(data);尝试{vardataStream=request.GetRequestStream();dataStream.Write(dataBytes,0,dataBytes.Length);数据流.关闭();}catch(Exceptionex){抛出;}}WebResponse响应=null;尝试{response=request.GetResponse();}catch(Exceptionex){抛出;}varresponseReader=newStreamReader(rStream,Encoding.UTF8);varresponseStr=responseReader.ReadToEnd();responseReader.Close();响应.关闭();我究竟做错了什么?为什么它的行为与来自Web浏览器的HTTP请求如此不同?这实际上给我的应用程序增加了200毫秒的延迟。这看起来像是Nagle算法与TCP延迟确认冲突的典型案例。在您的情况下,您发送一个小的Http请求(根据您的数字大约170个字节)。这可能小于MSS(最大段大小),这意味着Nagle的算法开始。服务器可能会延迟ACK,导致延迟高达500毫秒。有关详细信息,请参阅链接您可以通过ServicePointManager.UseNagleAlgorithm=false禁用Nagle(在发出第一个请求之前),请参阅MSDN。另请参阅Nagle的算法对小请求不友好的详细讨论,包括Wireshark分析。注意:在您的回答中,您在进行写-写-读时遇到了相同的情况。您可以在切换到读写模式时解决此问题。但我不相信您可以指示HttpWebRequest(或HttpClient)将小请求作为单个TCP写操作发送。在某些情况下,这可能是一个很好的优化。虽然它可能会导致一些额外的数组复制,从而对性能产生负面影响。200毫秒是Nagle算法的典型延迟。这引起了对在服务器端或客户端使用Nagling的怀疑。你说你正在使用来自MSDN的示例作为服务器......所以你去了。使用适当的服务器或禁用Nagling。假设内置的HttpWebRequest类有不必要的200毫秒延迟是不太可能的。别看。检查您的代码是否存在问题。看来HttpWebRequest真的很慢。有趣的事情:我使用套接字实现了我自己的HTTP客户端,我发现了为什么HttpWebRequest这么慢的线索。如果我将我的ASCII标头编码到它自己的字节数组中并将它们发送到流上,然后是我的数据中的编码字节数组,我基于套接字的HTTP客户端的行为与HttpWebRequest完全一样:首先它用一个数据填充一个缓冲区(部分标头),然后它部分使用另一个缓冲区(标头的其余部分),等待200毫秒,然后发送其余数据。代码:TcpClientclient=newTcpClient(server,port);NetworkStream流=client.GetStream();//发送出去stream.Write(headerData,0,headerData.Length);stream.Write(bodyData,0,bodyData.Length);stream.Flush();解决方案当然是在将两个字节数组发送到流之前附加它们。我的应用程序现在运行良好。单流代码如下:TcpClientclient=newTcpClient(server,port);NetworkStream流=client.GetStream();vartotalData=newbyte[headerBytes.Length+bodyData.Length];Array.Copy(headerBytes,totalData,headerBytes.Length);Array.Copy(bodyData,0,totalData,headerBytes.Length,bodyData.Length);//发送出去stream.Write(totalData,0,totalData.Length);stream.Flush();HttpWebRequest似乎在我写入请求流之前发送了标头,因此它可能类似于我的第一个代码示例。是否有意义?希望这可以帮助有同样问题的人!试试这个:YouneedtohandleyourIDisposables:以上是C#学习教程:HttpWebRequestuseschunkeddataveryslowly分享全部内容,如果对大家有用需要详细了解C#学习教程,希望大家多加注意——varrequest=(HttpWebRequest)WebRequest.Create(url);request.Method=动词;request.Timeout=超时;请求.Proxy=null;请求.KeepAlive=false;request.Headers.Add("内容编码","UTF-8");System.Net.ServicePointManager.Expect100Continue=false;request.ServicePoint.Expect100Continue=false;if((verb=="POST"||verb=="PUT")&&!String.IsNullOrEmpty(data)){vardataBytes=Encoding.UTF8.GetBytes(data);使用(vardataStream=request.GetRequestStream()){dataStream.Write(dataBytes,0,dataBytes.Length);}}字符串responseStr;使用(varresponse=request.GetResponse()){使用(varresponseReader=newStreamReader(rStream,Encoding.UTF8)){responseStr=responseReader.ReadToEnd();}}本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
