上传速度问题:HttpWebRequest [重复]

Posted

技术标签:

【中文标题】上传速度问题:HttpWebRequest [重复]【英文标题】:Upload Speed Issue : HttpWebRequest [duplicate] 【发布时间】:2012-12-12 18:22:54 【问题描述】:

我正在使用 HttpWebRequest 将文件上传到某个服务器,现在的问题是我遇到了速度问题。

我无法获得与使用浏览器 (Mozilla Firefox) 相同的上传速度,我获得的速度是我从浏览器获得的速度的 1/5。

这是我的 HttpWebRequest 对象的设置

//headers is a NameValueCollection type object,
//Method is a struct  GET, POST, HEAD 

        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
        request.UserAgent = headers["User-Agent"];
        request.KeepAlive = false;
        request.Accept = headers["Accept"];
        request.AllowAutoRedirect = AllowRedirect;
        request.Headers.Add(HttpRequestHeader.AcceptLanguage, "en-US,en;q=0.5");
        request.Method = Method.ToString();
        request.AllowWriteStreamBuffering = false;
        request.ReadWriteTimeout = 60000;

我一直启用的一些全局选项

        ServicePointManager.Expect100Continue = false;
        ServicePointManager.DefaultConnectionLimit = 200;
        ServicePointManager.MaxServicePointIdleTime = 2000;
        ServicePointManager.MaxServicePoints = 1000;
        ServicePointManager.SetTcpKeepAlive(false, 0, 0);

我如何分块发送文件...

            if (PostMethod == PostType.MultiPart && uploadFiles.Count > 0)
            
                for (int i = 0; i < uploadFiles.Count; i++)
                
                    string fileParam = uploadFiles.GetKey(i);
                    string tmpFilename = uploadFiles.Get(i);
                    string tmpData =
                    string.Format(
                        "--0\r\nContent-Disposition: form-data; name=\"1\"; filename=\"2\"\r\nContent-Type: 3\r\n\r\n", boundary, fileParam, Path.GetFileName(tmpFilename), MimeType.GetMimeByExtension(Path.GetExtension(tmpFilename)));
                    byte[] tmpBytes = Encoding.Default.GetBytes(tmpData);
                    writer.Write(tmpBytes, 0, tmpBytes.Length);
                    bSent += tmpBytes.Length;

                    arg.Progress = (int)(bSent * 100 / totalBytes);
                    arg.Speed = (bSent / sw.Elapsed.TotalSeconds);
                    OnProgress(arg);

                    //write the file
                    int fileBytesRead;

                    FileStream fileStream = File.Open(tmpFilename, FileMode.Open, FileAccess.Read, FileShare.Read);
// buffer size = 8192
                    while ((fileBytesRead = fileStream.Read(buffer, 0, BUFFER_SIZE)) > 0) 

                    
                        writer.Write(buffer, 0, fileBytesRead);
                        bSent += fileBytesRead;

                        int timeNow = Environment.TickCount;
                        if (timeNow - lastTime >= 500)
                        
                            lastTime = timeNow;
                            arg.Progress = (int)(bSent * 100 / totalBytes);
                            arg.Speed = (bSent / sw.Elapsed.TotalSeconds);
                            OnProgress(arg);
                        
                    

                    tmpBytes = Encoding.Default.GetBytes("\r\n");
                    writer.Write(tmpBytes, 0, tmpBytes.Length);
                    bSent += tmpBytes.Length;

                    arg.Progress = (int)(bSent * 100 / totalBytes);
                    arg.Speed = (bSent / sw.Elapsed.TotalSeconds);
                    OnProgress(arg);

                
            

我很乐意达到浏览器上传速度的 75%。

【问题讨论】:

与 Firefox 相比,该浏览器是否有任何可能影响该浏览器速度的附加插件。我有一位同事说他们在浏览器中上传速度很慢,让他们使用 Windows 默认地址导航,并且上传速度很快。事实证明,他们有一些插件会窃取数据并造成大量延迟。不过,我会尝试想出更好的东西。 @Greg - 不,我只有 2 个插件,Live HTTP Headers 和 TamperData! WebClient.UploadFile 没有被使用有什么原因吗? @Dan-o - 是的....一些 HTTP 请求与正常格式不同! 你上传的是什么数据?浏览器 (Firefox) 和 WebServer 是否有可能使用http compression?可能你的代码不是。 【参考方案1】:

两件事。

    您通过分块破坏了 TCP/IP 堆栈的目的。 TCP/IP 旨在处理近乎异步的数据传输。它将自己进行分块并继续发送块,直到完成或达到其未确认的最大块数。如果达到最大块数,它将等待 ACK(确认)继续 - 类似于信号量意识形态期望释放可以“堆叠”,AKA 单个 ACK​​ 包含它收到的最后一个点并且可以“释放” /acknowledge 多个块数据包) - 或请求超时。

    通过自己分块,必须完全确认每个块才能发送更多数据,因此您增加了开销。您仍在使用相同的连接,但实际上是在发出多个单独的请求。此外,如果 TCP/IP 块大小不是您的块大小的除数 (YOUR_CHUNK_SIZE % TCP_IP_CHUNK_SIZE != 0),那么您将留下一个延迟的 TCP/IP 块,该块必须超时并解析为伪 ACK;下次它可以在下一个块中得到确认。

    2.

另一个可能影响性能的选项是使用UseNagleAlgorithm property。当此属性设置为 true 时,TCP/IP 将尝试对 HTTP 连接使用 TCP Nagle 算法。 Nagle 算法在发送 TCP 数据包时聚合数据。在通过网络发送数据之前,它将小消息序列累积成较大的 TCP 数据包。使用 Nagle 算法可以优化网络资源的使用,尽管在某些情况下性能也会降低。通常对于恒定的大容量吞吐量,使用 Nagle 算法实现性能改进。但对于吞吐量较小的应用程序,可能会出现性能下降。

应用程序通常不需要更改默认值 UseNagleAlgorithm 属性设置为 true。然而,如果一个 应用程序正在使用低延迟连接,设置它可能会有所帮助 属性为 false

来自 MSDN:HttpWebRequest Class (System.Net)

【讨论】:

【参考方案2】:

这是我们可以提高上传速度的各种选项:-

http://bytes.com/topic/asp-net/answers/440179-how-speed-up-file-upload-2-0-a

在配置文件中用于大文件:---

把这个写在 web config system.web>

httpRuntime maxRequestLength="2097151"

这可能有助于在 IIS 7.0 中找到解决方案

把这个写在 web config system.web>httpModules

**add name="ITHitPutUploadProgressAndResumeModule" type="ITHit.WebDAV.Server.ResumableUpload.PutUploadProgressAndResumeModule, ITHit.WebDAV.Server"**

【讨论】:

它不是一个网络应用程序,它的WinForm【参考方案3】:

我通过搜索这个网站找到了答案。它似乎与".NET HttpWebRequest Speed versus Browser" 重复。

从那里发布的答案:

“第一次请求页面时,.net 会尝试检测代理设置。解决方案是传入一个空的 WebProxy 对象。这样它只会连接到远程服务器,而不是自动检测代理服务器。” - Markos

尝试添加

    request.Proxy = new WebProxy();

【讨论】:

我设置了request.Proxy = null,另外还有上传速度的问题,我必须上传大文件,比如 2 GB 文件,mozilla firefox 快 3 倍! 问题是上传速度,如果连接延迟几微秒对我来说没问题,但我需要更好的上传速度! 抱歉,这对您不起作用。我会尝试自己重新创建问题。 您是否尝试过将 ServicePointManager 值保留为默认值? DefaultConnectionLimit、MaxServicePointIdleTime 和 MaxServicePoints 可能会限制您的吞吐量。 另外,你可能想看看***.com/questions/7666268/…

以上是关于上传速度问题:HttpWebRequest [重复]的主要内容,如果未能解决你的问题,请参考以下文章

C# HttpWebRequest 表单上传

上传图像多部分表单 HTTPWebRequest - 将图像数据转换为字符串?

如何使用 HttpWebRequest 模拟浏览器文件上传

C#用HttpWebRequest上传数据的问题。

使用 HttpWebRequest 通过 PUT 上传文件时出错

使用 HttpWebRequest,将文件上传到 SharePoint 时,WebResponse 是未编译的 aspx 页面