首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >responseStream上的多线程HttpWebRequest随机挂起

responseStream上的多线程HttpWebRequest随机挂起
EN

Stack Overflow用户
提问于 2014-07-24 12:59:07
回答 3查看 799关注 0票数 1

我正在编写一个多线程的网络爬虫,它每秒使用数百个线程执行大量并发的happen请求,应用程序运行得很好,但有时(随机地)其中一个web请求挂在getResponseStream()上,完全忽略超时(当我同时执行数百个请求时会发生这种情况),使得爬行过程永远不会结束,奇怪的是,在fiddler中,这永远不会发生,应用程序永远不会挂起,调试真的很难,因为它是随机发生的。

我试着设置

Keep-Alive = false

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;

但我还是有奇怪的行为,有什么想法吗?

谢谢

HttpWebRequest代码:

代码语言:javascript
复制
  public static string RequestHttp(string url, string referer, ref CookieContainer cookieContainer_0, IWebProxy proxy)
    {
        string str = string.Empty;
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
        request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
        request.UserAgent = randomuseragent();
        request.ContentType = "application/x-www-form-urlencoded";
        request.Accept = "*/*";
        request.CookieContainer = cookieContainer_0;
        request.Proxy = proxy;
        request.Timeout = 15000;
        request.Referer = referer;
        //request.ServicePoint.MaxIdleTime = 15000;
        using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
        {
            using (Stream responseStream = response.GetResponseStream())
            {
                List<byte> list = new List<byte>();
                byte[] buffer = new byte[0x400];
                int count = responseStream.Read(buffer, 0, buffer.Length);
                while (count != 0)
                {
                    list.AddRange(buffer.ToList<byte>().GetRange(0, count));
                    if (list.Count >= 0x100000)
                    {
                        break;
                    }
                    count = 0;
                    try
                    {
           HERE IT HANGS SOMETIMES --->             count = responseStream.Read(buffer, 0, buffer.Length);
                        continue;
                    }
                    catch
                    {
                        continue;
                    }
                }
                //responseStream.Close();
                int num2 = 0x200 * 0x400;
                if (list.Count >= num2)
                {
                    list.RemoveRange((num2 * 3) / 10, list.Count - num2);
                }
                byte[] bytes = list.ToArray();
                str = Encoding.Default.GetString(bytes);
                Encoding encoding = Encoding.Default;
                if (str.ToLower().IndexOf("charset=") > 0)
                {
                    encoding = GetEncoding(str);
                }
                else
                {
                    try
                    {
                        encoding = Encoding.GetEncoding(response.CharacterSet);
                    }
                    catch
                    {
                    }
                }
                str = encoding.GetString(bytes);
               // response.Close();
            }
        }
        return str.Trim();
    }
EN

回答 3

Stack Overflow用户

发布于 2014-07-24 13:33:07

Timeout属性“获取或设置GetResponse和GetRequestStream方法的超时值(毫秒)。”默认值为100,000毫秒(100秒)。

ReadWriteTimeout属性“获取或设置写入或读取流时的超时(以毫秒为单位)。”默认值为300,000毫秒(5分钟)。

您设置了Timeout,但将ReadWriteTimeout保留为默认值,因此您的读取可能需要5分钟才会超时。您可能希望将ReadWriteTimeout设置为较低的值。您还可以考虑限制下载的数据大小。使用我的爬虫,我有时会偶然发现一个无休止的流,这最终会导致内存不足异常。

爬行时我注意到的另一件事是,有时关闭响应流会挂起。我发现,如果我想在读取整个流之前退出,就必须调用request.Abort来可靠地终止请求。

票数 1
EN

Stack Overflow用户

发布于 2014-07-24 13:33:19

在您提供的代码中没有任何明显的东西。

为什么注释掉response.Close()?

文档提示,如果不显式关闭,连接可能会耗尽。被释放的响应可能会关闭连接,但我认为仅仅释放所有资源并不是最优的。关闭响应也将关闭流,以使其被覆盖。

没有超时的系统挂起可能只是一个网络问题,使响应对象成为死鸭,或者问题是由于大量线程导致内存碎片。

查看任何可能产生模式的东西都可能有助于找到来源:

  1. 通常有多少个线程在运行(能否在较少的线程中捆绑请求集)
  2. 线程停止时的网络性能如何
  3. 发生时是否有特定的计数或范围
  4. 发生时最后处理的数据(是否有任何特定的控制字符或数据序列可能会扰乱流)

想问更多的问题,但是没有足够的口碑,所以只能回复。

祝好运!

票数 0
EN

Stack Overflow用户

发布于 2014-07-25 02:16:01

不同之处在于,我只读取流一次,然后解析结果。

代码语言:javascript
复制
       try
       {
           _webResponse = (HttpWebResponse)_request.GetResponse();
           if(_request.HaveResponse)
           {
               if (_webResponse.StatusCode == HttpStatusCode.OK)
               {
                   var _stream = _webResponse.GetResponseStream();
                   using (var _streamReader = new StreamReader(_stream))
                   {
                       string str = _streamReader.ReadToEnd();
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24925441

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档