【问题标题】:Socket exception in sending HTTP request without Connection header using sockets使用套接字发送没有连接标头的 HTTP 请求时的套接字异常
【发布时间】:2017-08-16 08:43:27
【问题描述】:

当我使用以下代码在 C# 中使用套接字发送 HTTP GET 请求时

    IPEndPoint RHost = new IPEndPoint(IPAddress.Parse("xxx.xxx.xxx.xxx"), 80);
    Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    socket.Connect(RHost);
    String req = "GET / HTTP/1.1\r\nHost: awebsite.com\r\n\r\n";

    socket.Send(Encoding.ASCII.GetBytes(req), SocketFlags.None);
    int bytes = 0;
    byte[] buffer = new byte[256];
    var result = new StringBuilder();

    do
    {
        bytes = socket.Receive(buffer, 0, buffer.Length, SocketFlags.None);
        result.Append(Encoding.ASCII.GetString(buffer, 0, bytes));
    }
    while (bytes > 0);

我明白了

System.Net.Sockets.SocketException: '一个现有的连接是 被远程主机强行关闭'

当我在请求中添加Connection: Close 标头时,它可以正常工作。 但是使用 Burp Suite 中的中继器工具,我可以在不设置 Connection: Close 标头的情况下发送和接收来自服务器的响应。

注意事项:

  • 我必须使用套接字。
  • 我遇到这个问题的网站很少,而不是每个网站

【问题讨论】:

  • 您是否尝试设置超时?例如socket.ReceiveTimeout = 1000; ?

标签: c# sockets httprequest


【解决方案1】:

您正在发送 HTTP/1.1 请求。如果没有显式的 Connection: close,则存在带有 HTTP/1.1(不同于 HTTP/1.0)的隐式 Connection: keep-alive。这意味着服务器可能会在响应完成后等待同一 TCP 连接中的新请求,如果没有新请求到达,有时会关闭连接。稍后关闭可能会使用 RST 来完成,这会导致您看到的错误。

但是,您的代码希望服务器的行为有所不同:它希望服务器在请求完成后关闭连接,而不是等待更多请求,也不要使用 RST 关闭空闲连接。

要解决此问题,您必须调整请求以使服务器行为符合您的期望或调整期望。
第一个可以通过显式添加 Connection: close 标头或简单地使用 HTTP/1.0 而不是 HTTP/1.1 来完成。推荐使用后一种,因为这也会导致更简单的响应(没有分块响应)。
如果您想调整您的期望,则必须正确解析服务器响应:首先读取标头,然后检查Transfer-Encoding: chunkedContent-length,然后根据这些标头的内容读取响应正文。详情见the HTTP standard

【讨论】:

  • 谢谢,我用 HTTP/1.0 测试了我的代码,它的工作没有问题,但是,我不能操纵请求(更改 HTTP 版本或添加/删除标头)。所以我想我必须检查传输编码的响应标头:分块或内容长度,但想知道是否可以保证响应具有这些标头之一!?
  • @HadiRj:如果你实现了一个协议,强烈建议你熟悉标准,在这种情况下是RFC 2616。从这里您将看到有三种方法可以指定响应结束的位置:通过分块编码,通过内容长度,如果这些都不是通过连接关闭给出的。
猜你喜欢
  • 2013-05-14
  • 2022-11-15
  • 1970-01-01
  • 1970-01-01
  • 2012-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-22
相关资源
最近更新 更多