【问题标题】:WebClient is opening a new connection each time I download a file and all of them stay established每次我下载文件时,WebClient 都会打开一个新连接,并且它们都保持建立状态
【发布时间】:2013-05-11 21:23:58
【问题描述】:

我在找出如何关闭WebClient 建立的连接时遇到问题。我创建了一个新的WebClient 对象,然后多次调用DownloadFile 方法,但是,它总是为每次调用创建一个新连接并且这些连接保持打开状态(已建立状态),我可以在 TCPView 中看到所有已建立的连接.

如果当我处置 Webclient 时,他们仍然保持稳定,还有什么让我更烦恼的事情......? 下载完成后如何强制关闭连接?

我已经尝试派生 WebClient 并将 keep alive 手动设置为 false,我的应用配置也允许足够的连接。

<connectionManagement>
  <add address="*" maxconnection="1000"/>
</connectionManagement>

【问题讨论】:

  • 我已经编辑了你的标题。请参阅“Should questions include “tags” in their titles?”,其中的共识是“不,他们不应该”。
  • 最大连接数是多少?看起来像保持活动状态。
  • @usr 即使是keep-alive,如果webclient被释放,连接不应该被关闭吗?
  • .NET 将跨对象实例的连接池化。这很正常。再说一次,有多少?

标签: c# http


【解决方案1】:

简短回答:您不需要手动关闭连接。它们在幕后为您管理。

HTTP/1.1 连接不会在请求完成后立即关闭,以便以更及时和有效的方式处理对同一服务器的多个请求(例如 Web 浏览器从单个站点请求多个文件)。您不必担心这一点或手动关闭它们,因为它们会在一段时间后超时。会不会出错?

如果有问题,您可以尝试从WebClient 继承并覆盖GetWebRequest 方法以手动设置KeepAlive,例如:

public class NoKeepAlivesWebClient : WebClient
{
    protected override WebRequest GetWebRequest(Uri address)
    {
        var request = base.GetWebRequest(address);
        if (request is HttpWebRequest)
        {
            ((HttpWebRequest)request).KeepAlive = false;
        }

        return request;
    }
}

我也总是建议使用 WebClient 的使用模式:

using (var client = new NoKeepAlivesWebClient())
{
    // Some code
}

最后,这里有一些关于 HTTP/1.1 中持久连接的 RFC 信息:

http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html

还有一个更友好的维基百科条目:

http://en.wikipedia.org/wiki/HTTP_persistent_connection

编辑:

抱歉。我从您编辑的问题中看到,您已经尝试过类似上述的方法,但没有成功。

但是,我无法重现您的问题。根据TCPView,我使用NoKeepAlivesWebClient编写了一个小程序,并在使用后成功关闭了连接。

static void Main(string[] args)
{
    // Random test URLs
    var urls = new List<string> {
        "http://msdn.microsoft.com/en-us/library/tt0f69eh.aspx",
        "http://msdn.microsoft.com/en-us/library/system.net.webclient.allowreadstreambuffering.aspx",
        "http://msdn.microsoft.com/en-us/library/system.net.webclient.allowwritestreambuffering.aspx",
        "http://msdn.microsoft.com/en-us/library/system.net.webclient.baseaddress.aspx",
        "http://msdn.microsoft.com/en-us/library/system.net.webclient.cachepolicy.aspx",
        "http://msdn.microsoft.com/en-us/library/system.net.webclient.credentials.aspx",
        "https://www.youtube.com/",
        "https://www.youtube.com/feed/UClTpDNIOtgfRkyT-AFGNWVw",
        "https://www.youtube.com/feed/UCj_UmpoD8Ph_EcyN_xEXrUQ",
        "https://www.youtube.com/channel/UCn-K7GIs62ENvdQe6ZZk9-w" };

    using (var client = new NoKeepAlivesWebClient())
    {
        // Save each URL to a Temp file
        foreach (var url in urls)
        {
            client.DownloadFile(new Uri(url), System.IO.Path.GetTempFileName());
            Console.WriteLine("Downloaded: " + url);
        }
    }
}

这里还有一个关于同一问题的 SO 问题:

C# get rid of Connection header in WebClient

【讨论】:

  • 感谢所有信息,但是我已经尝试过完全相同的事情,没有运气,我还尝试将 Timeout 和 ReadWriteTimeout 设置为 10 秒,但也没有效果。我需要关闭它们,因为我使用了大量的 DownloadFile,过了一段时间,我在 tcpviews 中有 200 个已建立的连接,这没有任何意义
  • 抱歉,@Lasty01 在发布我的答案之前我没有看到您的编辑。我已经对其进行了编辑,以便为您添加另一个选项。
  • 再次感谢,但似乎没有任何效果......我现在尝试了这个:protected override WebRequest GetWebRequest(Uri address) { WebRequest request = base.GetWebRequest(address); if (request is HttpWebRequest) { var webRequest = request as HttpWebRequest; webRequest.CookieContainer = CookieContainer; webRequest.KeepAlive = false; webRequest.Timeout = 10000; webRequest.ReadWriteTimeout = 10000; } 返回请求; }
  • @Lasty01 - 恐怕我无法重现这个问题。您确定是通过 HTTP 还是 HTTPS 下载?
  • 好吧,我的错,我发现了错误,我正在调用 OpenRead 以在其他地方获取文件大小,并且我正在处理 webclient,但这还不够,我必须存储 OpenRead 返回的流在一个 var 中并明确地处理它,很抱歉这里的混乱,问题已解决,谢谢大家。
猜你喜欢
  • 2011-10-14
  • 2019-02-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多