C#GetResponse没有回来

时间:2016-11-18 11:43:32

标签: c# httprequest httpwebresponse

我有一个奇怪的问题。我的.NET DataController向Java服务器(REST)发送响应。一切正常,但是当我经常发送响应时,突然GetResponse方法不会回来就会挂起。 我不知道问题是什么。

这是我的代码

ServicePointManager.DefaultConnectionLimit = 20;

public string HttpGet(string url, string requestAccept)
{
  if(string.IsNullOrEmpty(url))
    throw new Exception("HttpGet: no REST service URL provided");
  if(string.IsNullOrEmpty(requestAccept))
    requestAccept = defaultRequestAccept;

  if(!url.Equals("pc/alive"))
  {
    if(string.IsNullOrEmpty(SessionId))
    {
      if(string.IsNullOrEmpty(Authorization()))
        throw new WebException("HttpGet: no login");
    }
  }

  int tries = RestAccessData.MaxReconnect;
  string result = string.Empty;

  do
  {
    try
    {
      var request = NewWebRequest(url, "GET", false, true, requestAccept);

      using(var response = request.GetResponse() as HttpWebResponse)
      {
        UpdateSessionId(response);

        HttpStatusCode statusCode = response.StatusCode;
        LOG.Debug("...StatusCode: {0} ({1})", (int) response.StatusCode, response.StatusDescription);

        if((int) response.StatusCode < 500)
          lastContactWithServer = DateTime.Now.Ticks;

        switch(statusCode)
        {
        // Informational 1xx
        case HttpStatusCode.Continue: // 100
        case HttpStatusCode.SwitchingProtocols: // 101

          throw new HttpResponseException(response);

        // Successful 2xx
        case HttpStatusCode.OK: // 200

          result = ReadContent(response);
          response.Close();

          return (result);

        case HttpStatusCode.NoContent: // 204 The server has fulfilled the request but does not need to return an entity-body, and might want to return updated metainformation.

          response.Close();
          return (string.Empty);

        case HttpStatusCode.Created: // 201
        case HttpStatusCode.NonAuthoritativeInformation: // 203

          result = ReadContent(response);
          throw new HttpResponseException(response, result);

        case HttpStatusCode.Accepted: // 202 The request has been accepted for processing, but the processing has not been completed.
        case HttpStatusCode.ResetContent: // 205 The server has fulfilled the request and the user agent SHOULD reset the document view which caused the request to be sent.
        case HttpStatusCode.PartialContent: // 206 The server has fulfilled the partial GET request for the resource.

          throw new HttpResponseException(response);

        case HttpStatusCode.Unauthorized:

          throw new HttpResponseException(response);

        default:

          throw new HttpResponseException(response);
        }
      }
    }
    catch(WebException ex)
    {
      HandleWebException(ex);
    }
    catch(HttpResponseException ex)
    {
      throw ex;
    }
    catch(SystemException ex)
    {
      LOG.Error(ex, "caused a(n) {0}", ex.GetType().Name);
    }
    catch(Exception ex)
    {
      LOG.Warn(ex, "HttpGet: An error occured while trying to contact the server. Reason: {0}", ex.Message);
      throw new UserException("An error occured while trying to contact the server.", ex);
    }
  }
  while(0 < tries--);

  return (string.Empty);
}

private HttpWebRequest NewWebRequest(string urlAsString, string requestType, bool withContentType, bool applicationJson, string requestAccept)
{
  urlAsString = string.Format("{0}{1}", RestAccessData.GetUrl(), EncodeUrl(urlAsString));
  Uri url;

  if(!Uri.TryCreate(urlAsString, UriKind.Absolute, out url))
    throw new NotSupportedException("url is not compatible");

  LOG.Info("RESTUrl {0}", urlAsString);

  try
  {
    var request = HttpWebRequest.Create(url) as HttpWebRequest;

    if(!string.IsNullOrEmpty(SessionId))
    {
      CookieContainer cookies = new CookieContainer();
      Cookie cookie = new Cookie
      {
        Name = "JSESSIONID",
        Value = SessionId,
        Domain = url.Host
      };

      cookies.Add(cookie);
      request.CookieContainer = cookies;
    }

    request.Timeout = RestAccessData.Timeout;
    request.Method = requestType;
    request.AllowAutoRedirect = true;
    request.AllowWriteStreamBuffering = true;
    request.KeepAlive = false;
    request.ContentLength = 0;
    request.Headers["Accept-Charset"] = "utf-8";
    request.Accept = requestAccept;
    request.UserAgent = LvsClient;

    if(withContentType)
      request.ContentType = applicationJson ? defaultApplicationJson : defaultApplicationWwwForm;

    if(!string.IsNullOrEmpty(credential.UserName) && !string.IsNullOrEmpty(credential.Password))
      request.Headers["Authorization"] = string.Format("Basic {0}", Convert.ToBase64String(Encoding.UTF8.GetBytes(string.Format("{0}:{1}", credential.UserName, credential.Password))));

    return (request);
  }
  catch(Exception ex)
  {
    throw new UserException(TH.Translate("NewWebRequest caused an error"), ex);
  }
}

问题出在哪里?

2 个答案:

答案 0 :(得分:0)

这条线让我感到不舒服:

using(var response = request.GetResponse() as HttpWebResponse)

如果响应不是HttpWebResponse,那么它永远不会被处理 - as运算符会给你'null。

答案 1 :(得分:0)

我找到了解决方案。这篇关于Understanding MaxServicePointIdleTime and DefaultConnectionLimit的MSDN文章非常有用。使用 MaxServicePointIdleTime 属性后,阅读此评论

  

change the connection limit at any time

我在连接活动和连接关闭之间找到了一个很好的平衡点。使用MaxServicePointIdleTime和DefaultConnectionLimit后,我的客户端工作正常。