httpwebrequest下载文件失败的解决方案

    项目转战页游(?),需要在首包开始游戏后,背景下载后续的资源。这个模块是用httpwebrequest实现的,也考虑过webClient,据说webclient没法显示进度和错误码(主程说的,其实好像也是有的)。那就用httpwebrequest的。采用异步下载,例子参考至msdn,连接如下:https://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.begingetresponse(v=vs.110).aspx

    实际项目中未使用ManualResetEvent。实际测试结果会遇到问题,经常在endGetResponse吃,报错,捕获webexception,status=receiveFailture。google后,发现相关的解决方案比较少。反而msdn针对各种status有相关解决推荐。连接如下:https://docs.microsoft.com/en-us/dotnet/framework/network-programming/understanding-webrequest-problems-and-exceptions。

    通过解决推荐,了解到默认http的默认连接数是2,首先这个http连接数本身很少,可以通过设置DefaultConnectionLimit将连接数调大点。往往,假设connection不正常的关闭,会导致connection不会被释放,从而导致连接数被占用。仔细查代码,发现了喜感的事:

    private long GetLength(string url)
    {
        HttpWebRequest _request = WebRequest.Create(url) as HttpWebRequest;
        _request.Method = "HEAD";
        HttpWebResponse _response = _request.GetResponse() as HttpWebResponse;
        long _ret = _response.ContentLength;
        _response.Close();//这里是新加的,切记response必须要关闭。
        return _ret;

    }
    这里用上述同步方法获得url对应的资源的大小,用于显示加载的进度。忘记关闭,就会导致connection被占用,释放不了。然后产生receive Failture。最后,在endResponse在获得资源的大小即可。综上,切记getResponse或者endGetResponse,同步、异步方法后都要记得调用response.close方法。

    将默认连接数改大,同时修正上述时,发现不会在大批量的出现receive failture了。但是偶尔还会有资源下载失败的情况。这时候根据msdn推荐,进行了如下设置:

            //创建一个初始化请求对象  
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(url));
            request.KeepAlive = false;//这个有用
            request.Proxy = WebRequest.DefaultWebProxy;//不使用代理,减少自动搜索代理的过程,提升性能

            //设置下载相关参数  
            requestState.RetryTime = 4;//增加下载失败重试次数
            requestState.StateObject = this;
同时,在捕获到一些status时,重新尝试下载几次。基本上就解决了资源下载不下来的问题。
    private bool IsRetryable(WebException ex)
    {
        return
            ex.Status == WebExceptionStatus.ReceiveFailure ||
            ex.Status == WebExceptionStatus.ConnectFailure ||
            ex.Status == WebExceptionStatus.KeepAliveFailure;
    }

   catch (WebException e)
        {
            if (e.Status == WebExceptionStatus.RequestCanceled)
                return;
            Debug.LogErrorFormat("\nRespCallback Exception raised!");
            Debug.LogErrorFormat("\nMessage:{0}", e.Message);
            Debug.LogErrorFormat("\nStatus:{0}", e.Status);
            Debug.LogErrorFormat("请求资源响应失败,资源url{0}", m_RequestState.Url);
            
            Connection.pool.log("ResponseCallback资源异常 WebException StackTrace :{0}, Message:{1}, Status:{2}, 资源url:{3}。", e.StackTrace, e.Message, e.Status, m_RequestState.Url);
            if (IsRetryable(e))
            {
                TryRequest(requestState);
                System.Threading.Thread.Sleep(2);//当前下载线程休息2ms
            }
            else
            {
                int _stateCode = 0;
                if (requestState.Response != null)
                    _stateCode = (int)requestState.Response.StatusCode;

                Connection.pool.log("下载资源异常Response Code :{0}, Message:{1}, 资源url:{2}。", _stateCode, e.Message, m_RequestState.Url);
                m_IsSuccess = true;
                requestState.StateObject.DownLoadCompleted();
                return;
            }
            //m_IsSuccess = false;
            //requestState.StateObject.DownLoadCompleted();
        }
注:404错误要忽略哦。
参考:

 http://www.cnblogs.com/summer_adai/archive/2013/04/26/3045253.html


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值