【问题标题】:C# https request always tunnel to server but Java only onceC# https 请求总是通过隧道连接到服务器,但 Java 只有一次
【发布时间】:2014-03-12 01:43:02
【问题描述】:

我正在将 JAVA 程序转换为向服务器发送 https 请求的 C#。这是我登录到服务器然后从服务器注销的程序。

  var login_httpWebRequest = (HttpWebRequest)WebRequest.Create(m_base_url + "session/login");
  login_httpWebRequest.ContentType = "application/json; charset=UTF-8";

  var logout_httpWebRequest = (HttpWebRequest)WebRequest.Create(m_base_url + "session/logout");
  logout_httpWebRequest.ContentType = "application/json; charset=UTF-8";

  CookieContainer cookieJar = new CookieContainer();
  login_httpWebRequest.CookieContainer = cookieJar;


  using (StreamWriter streamWriter = new StreamWriter(login_httpWebRequest.GetRequestStream()))
  {
      streamWriter.Write("{username:xxxxxx,password:yyyyyyy}");
  }
  var httpResponse = (HttpWebResponse)login_httpWebRequest.GetResponse();
  var login_cookies = httpResponse.Cookies;

  logout_httpWebRequest.CookieContainer = new CookieContainer();
  httpWebRequest.CookieContainer.Add(login_cookies);
  using (StreamWriter streamWriter = new StreamWriter(logout_httpWebRequest.GetRequestStream()))
  {
      streamWriter.Write("{}");
  }

  var httpResponse = (HttpWebResponse)login_httpWebRequest.GetResponse();

但是我的 C# 程序比原来的 JAVA 程序需要更多的时间,然后我使用 Fiddler 工具检查了请求。所以我发现每个请求 C# Tunnel 到服务器。但 JAVA 程序只有一次。

下图

  • 绿色表示由 JAVA 程序发送到服务器的请求(隧道->登录->注销)。
  • 红色表示由 C# 程序发送到服务器的 C# 程序请求(隧道->登录->隧道->注销)。

任何人都知道如何避免 C# Http 客户端对每个请求的隧道。

【问题讨论】:

  • 检查KeepAlive property,默认情况下应该是true,但也许你的实际代码会重置它...
  • 每个请求都有Connection: Keep-Alive 标头。 JAVA程序和C#发送的两个请求是相同的。我猜问题出在 C# 代码中。应该有一种使用相同会话的方法。
  • 你有想过这个吗?
  • 检查嗅探器是否 java 使用的是 http1.0 或 http1.1。还要检查java是否是GZIP。为什么每次都是c#登录?连接是否关闭? HTTP 使用 TCP 作为传输层。 TCP 可能会显示一个 [FIN],它表示连接已关闭。您也可以使用 from cmd.exe >Netstat -a 来验证连接的状态,看看它是否关闭。
  • 我的猜测是 WebRequest 的每个实例都在创建自己的连接。我真的没有看到一种方法可以使它重新使用连接。通常我使用 HttpClient 代替,并且每个基本 url 只创建一个实例。有关更多信息,请参阅aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong

标签: c# java http network-programming


【解决方案1】:

您是否尝试过使用 HttpClient 而不是 WebRequest?我写了这个没有办法测试它所以希望它很接近......

    using (HttpClientHandler handler = new HttpClientHandler())
    {
        CookieContainer cookies = new CookieContainer();
        handler.CookieContainer = cookies;

        using (HttpClient httpClient = new HttpClient(handler))
        {
            httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json; charset=UTF-8"));

            HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, m_base_url + "session/login");
            requestMessage.Content = new StringContent("{username:xxxxxx,password:yyyyyyy}"); ;

            HttpResponseMessage loginResponse = await httpClient.SendAsync(requestMessage);

            // The HttpClient should already have the cookies from the login so
            // no need to transfer
            requestMessage = new HttpRequestMessage(HttpMethod.Get, m_base_url + "session/logout");
            requestMessage.Content = new StringContent("{}");

            HttpResponseMessage logoutResponse = await httpClient.SendAsync(requestMessage);
        }
    }

【讨论】:

  • 这就是我的伙计!感谢您的解决方案。解决方案是:使用 HttpClient 而不是原始 HttpRequestMessage。
猜你喜欢
  • 1970-01-01
  • 2019-11-12
  • 2020-09-30
  • 1970-01-01
  • 1970-01-01
  • 2012-03-20
  • 2017-01-01
  • 2020-07-05
  • 2012-06-21
相关资源
最近更新 更多