HttpWebRequest呼叫后超时无法正常工作

时间:2018-08-06 07:01:09

标签: c# post proxy timeout httpwebrequest

当IP正确时,我看不到任何问题,但是当IP断开时,超时值不起作用,超时需要75秒或80秒。....没有代理的相同代码也可以在15秒内超时,这是我设置的值。

是代理级别限制还是任何编码问题...我对此进行了大量研究,并尝试了Google的许多尝试,但无济于事。

这是我的代码

{
    HttpWebRequest ObjHttpWebRequest = null;
    HttpWebResponse objHttpWebResponse = null;
    Stopwatch watch = new Stopwatch();
    string strReturn = string.Empty;
    string validUrl = "false";
    try
    {
        watch.Start();
        string DATA = "postdata";
        ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(MyCertValidationCb);
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
        ObjHttpWebRequest = (HttpWebRequest)WebRequest.Create("https://196.234.502.247:4510/path");
        ObjHttpWebRequest.Timeout = 15000;
        ObjHttpWebRequest.Method = "POST";
        ObjHttpWebRequest.ContentType = "application/json";
        ObjHttpWebRequest.ContentLength = DATA.Length;
        {
            WebProxy proxy = new WebProxy();
            proxy.Address = new Uri("http://proxy.com");
            proxy.UseDefaultCredentials = true;
            ObjHttpWebRequest.Proxy = proxy;
        }
        X509Certificate2 X509cert2_client = new X509Certificate2(HttpContext.Current.Request.PhysicalApplicationPath + @"\folder\test.pfx", "test");
        ObjHttpWebRequest.ClientCertificates.Add(X509cert2_client);

        byte[] byteArray = Encoding.UTF8.GetBytes(DATA);
        ObjHttpWebRequest.ContentLength = byteArray.Length;
        Stream objRequestStream = ObjHttpWebRequest.GetRequestStream();
        objRequestStream.Write(byteArray, 0, byteArray.Length);
        objRequestStream.Close();

        using (objHttpWebResponse = ObjHttpWebRequest.GetResponse() as HttpWebResponse)
        {
            using (var objResponseStream = objHttpWebResponse.GetResponseStream())
            {
                using (var objResponseStreamReader = new StreamReader(objResponseStream, Encoding.UTF8))
                {
                    strReturn = objResponseStreamReader.ReadToEnd();
                    objResponseStreamReader.Close();
                }
                objResponseStream.Close();
            }
            objHttpWebResponse.Close();
        }
    }
    catch (Exception ex)
    {
        HttpContext.Current.Response.Write(ex.Message);
    }
    finally
    {
        watch.Stop();
        if (ObjHttpWebRequest != null) ObjHttpWebRequest.Abort();
        if (objHttpWebResponse != null) objHttpWebResponse.Close();
        HttpContext.Current.Response.Write(strReturn+ "--"+ watch.Elapsed.TotalSeconds.ToString()+"__"+ validUrl);
    }
}

1 个答案:

答案 0 :(得分:0)

根据MSDN Documentation,使用主机名可能会导致超时问题:

  

域名系统(DNS)查询最多可能需要15秒才能返回或超时。如果您的请求包含需要解析的主机名,并且您将Timeout设置为小于15秒的值,则可能需要15秒或更长时间才能引发WebException来指示您的请求超时。

我不确定这是否是原始问题,我会尝试以任何一种方式来识别它,但是您仍然可以自己实施超时以使其正常工作:

byte[] byteArray = Encoding.UTF8.GetBytes(DATA);
ObjHttpWebRequest.ContentLength = byteArray.Length;

var cancelSource = new CancellationTokenSource();
var requestHandlingTask = DoRequestHandling(ObjHttpWebRequest, byteArray, cancelSource.Token);

if (await Task.WhenAny(requestHandlingTask, Task.Delay(TIMEOUT)) == requestHandlingTask)
{
    // The task completed inside the timeout
    strReturn = requestHandlingTask.Result;
}
else
{
    // Timeout handling
    cancelSource.Cancel();

    // ...
}

在请求处理过程中,只要有可能(方法调用仍将运行更长的时间),我们就会检查取消令牌,并取消其余操作,同时主逻辑可以在另一个线程上继续进行。

static async Task<string> DoRequestHandling(HttpWebRequest request, byte[] arrByteData, CancellationToken cancelToken)
{
    string strReturn = String.Empty;

    var requestStream = await request.GetRequestStreamAsync()
        .ConfigureAwait(false);

    if (!cancelToken.IsCancellationRequested)
    {
        requestStream.Write(arrByteData, 0, arrByteData.Length);
        requestStream.Close();

        if (!cancelToken.IsCancellationRequested)
        {
            using (var response = await request.GetResponseAsync().ConfigureAwait(false) as HttpWebResponse)
            using (var responseStream = response.GetResponseStream())
            using (var responseStreamReader = new StreamReader(responseStream, Encoding.UTF8))
            {
                strReturn = await responseStreamReader.ReadToEndAsync()
                    .ConfigureAwait(false);
            }
        }
        else
        {
            // Request was cancelled -> exit
        }
    }
    else
    {
        // Request was cancelled -> exit
    }

    return strReturn;
}