C# HttpWebRequest 请求 常出现的问题

      一、GetResponse操作超时问题 

      最近在写一个爬网页的程序,可是每次才下载20几个页面就报“操作超时 ”的问题,上“度娘”、“谷哥”去查了好久,有的人说每次用完HttpWebRequest 要用request.Abort()将请求关闭,有的说要设置超时时间“request.Timeout = 200000”,有的说有可能是服务器连接过多,要少点并发,要加“DefaultConnectionLimit=50”,还有的人说可能是服务器将程序的请求当成异常请求直接拒了,所以要设置“request.Method = "GET";request.UserAgent = "Mozilla/5.0 (Windows NT 5.1; rv:19.0) Gecko/20100101 Firefox/19.0";”,可是这些我都做了,还是有提示“操作超时”,怎么办呢?于是,我在整合以上配置的同时,加上了响应超时判断,“ if (response.StatusCode == HttpStatusCode.RequestTimeout)”,最后终于可以了,为了让更多人受益,所以把结果分享给大家。我的代码如下:

request = (HttpWebRequest)WebRequest.Create(m_uri);
                request.KeepAlive = false;
                request.Method = "GET";
                request.UserAgent = "Mozilla/5.0 (Windows NT 5.1; rv:19.0) Gecko/20100101 Firefox/19.0";

                
                //如果服务器返回错误,他还会继续再去请求,不会使用之前的错误数据,做返回数据
                request.ServicePoint.Expect100Continue = false;
                request.Timeout = 200000;
                ServicePointManager.DefaultConnectionLimit = 20;

<span style="white-space:pre">		</span>//关键可能就是这个位置
                Monitor.Enter(this);
                using (response = (HttpWebResponse)request.GetResponse())
                {
                    if (response.StatusCode == HttpStatusCode.RequestTimeout)

                    {
                        Thread.Sleep(1000);
                        return null;
                    }
                    else
                    {
                        stream = response.GetResponseStream();

                        if (!response.ContentType.ToLower().StartsWith("text/"))
                        {
                            SaveBinaryFile(response);
                            return null;
                        }

                        string buffer = "", line;

                        reader = new StreamReader(stream, System.Text.Encoding.GetEncoding("gb2312"));

                        while ((line = reader.ReadLine()) != null)
                        { 

				buffer += line + "\r\n";
                        }
                        request.Abort();
                        return buffer;
                    }
                }

二、基础连接已关闭,发送时发生错误处理

在request 请求前面加上

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3; 试试

三、

随着REST风格的流行,直接通过 HttpWebRequest 进行服务调用的客户端应用越来越多。这里总结一些可能需要费时调查的经验,希望能帮助大家。 
1. 用完的HttpWebRequest要Abort()或者要把 Response.Close() 
否则会导致请求Timeout。 (HttpWebRequest.Method默认是GET)

static   void  Main( string [] args)  
{  
    for  ( int  i = 0; i < 10; i++)  
    {  
        Console.Write( "[{0}] Request - " , i + 1);  
        TryGet( "https://login.live.com/" );  
    }  
    Console.Read();  
}  
static   void  TryGet( object  obj)  
{  
    try   
    {  
        HttpWebRequest webReq =  null ;  
        string  url = ( string )obj;  
        webReq = (HttpWebRequest)HttpWebRequest.Create(url);  
        webReq.Timeout = 20 * 1000;  
        var resp = webReq.GetResponse()  as  HttpWebResponse;  
        resp.Close();  
        Console.WriteLine( "Get Response StatusCode: {0}({1})" ,   
            resp.StatusCode, ( int )resp.StatusCode);  
    }  
    catch  (WebException we)  
    {  
        Console.WriteLine( "Get Response StatusCode: {0}({1})" ,  we.Status, ( int )we.Status);  
    }  
    catch  (Exception ex)  
    {  
        Console.WriteLine(ex);  
    }  
}  


上面的代码,会从第3次Request开始出现Timeout,因为GetResponse 后 Stream打开未关闭。 
 
解决方法:上面的代码中加上 resp.Close(); 或者 webReq.Abort(); 就能解决。 

2. 多线程中调用 HttpWebRequest 时,需要设置 ServicePointManager.DefaultConnectionLimit 数(默认连接数是 2)。 
当多线程请求时,同时的连接数超过Limit时,GetResponse会抛出 Timeout WebException。

  1. // 用多线程同时发出4个请求   
  2. WaitCallback methodTarget =  new  WaitCallback(TryGet);  
  3. ThreadPool.QueueUserWorkItem(methodTarget,  "https://login.live.com/" );  
  4. ThreadPool.QueueUserWorkItem(methodTarget,  "https://login.live.com/" );  
  5. ThreadPool.QueueUserWorkItem(methodTarget,  "https://login.live.com/" );  
  6. ThreadPool.QueueUserWorkItem(methodTarget,  "https://login.live.com/" );  

解决方法:在GetResponse()之前设置 ServicePointManager.DefaultConnectionLimit = 100; 

3.  当请求一个基于SSL的服务时,默认的验证行为都在 ServicePointManager 定义: 
ServicePointManager.CheckCertificateRevocationList = true;

如果请求的服务端证书没有第三方的认证支持,则请求会失败,如果要完全信任服务端证书,则可以将 
CheckCertificateRevocationList  设为 false。 

4. 可以在 <system.net> 配置节中配置 HttpWebRequest 的属性,包括 WebProxy

  1. <system.net>    
  2.   <connectionManagement>    
  3.   </connectionManagement>   
  4.   <defaultProxy>    
  5.     <proxy proxyaddress= "http://xxx.xxx.xxx.xxx:xxx"  bypassonlocal= "False" />    
  6.   </defaultProxy>   
  7.   <settings>    
  8.       <httpWebRequest useUnsafeHeaderParsing= "true" />   
  9.       <servicePointManager checkCertificateName= "true"      
  10.                            checkCertificateRevocationList= "true"       
  11.                            enableDnsRoundRobin= "true"      
  12.                            expect100Continue= "true"        
  13.                            useNagleAlgorithm= "true" />      
  14.   </settings>   
  15. </system.net>  

错误提示的Message为:

基础连接已经关闭: 发送时发生错误。

InnerException为:

从传输流收到意外的 EOF 或 0 个字节。

试了网上的N种方法,以下是本次的解决方案:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;

把网上找到的解决方案列一下,没准就能解决了你的问题

以下是网上找到的解决方案:

1. request.ProtocolVersion = HttpVersion.Version10;

2. ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);

3.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;

4.换个UserAgent试试

5.在App.config中添加以下内容:

<system.net>
  <settings>
   <httpWebRequest useUnsafeHeaderParsing="true"/>
  </settings>
 </system.net>

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值