繁体   English   中英

C 原始套接字 HTTP 请求总是返回状态 400

[英]C Raw Sockets HTTP Request Always Returning Status 400

我通常会写一堆 Typescript/Javascript 代码,我认为 HTTP 协议是理所当然的。 我决定编写一个 C++ 程序,该程序可以使用套接字向给定的 URL 发出 GET 请求,以了解有关 HTTP 工作原理的更多信息。 我已经编码了我认为我应该做的基本结构:

  1. 创建套接字
  2. 将套接字连接到主机
  3. 逐字节发送请求
  4. 逐字节接收响应

问题是请求总是返回状态码 400:

>>>> Request sent:
GET /links HTTP/1.1


>>>> Response received:
HTTP/1.1 400 Bad Request
Server: cloudflare
Date: Sun, 11 Oct 2020 05:57:11 GMT
Content-Type: text/html
Content-Length: 155
Connection: close
CF-RAY: -

<html>
<head><title>400 Bad Request</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<hr><center>cloudflare</center>
</body>
</html>

这是我用来创建套接字并将其连接到主机的代码:

    // ---- Create the socket
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) error("!!!! ERROR opening socket");

    // ---- Look up (and parse) the server host, route
    std::string host = parseHost(url);
    std::string route = parseRoute(url);
    struct hostent *server = gethostbyname(host.c_str()); // host.c_str())
    if (server == NULL)
        error("!!!! ERROR, no such host");

    // ---- Fill in the server address structure
    struct sockaddr_in serv_addr;
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT); // PORT
    memcpy(&serv_addr.sin_addr.s_addr, server->h_addr, server->h_length);

    // ---- Connect the socket to the given url's host
    const int didConnect = connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
    if (didConnect < 0) error("!!!! ERROR connecting to host");

如果这个逻辑看起来是正确的,那么这里是发送请求和接收响应的代码:

    // ---- Send the GET request byte by byte
    int bytes, sent, received;
    char response[MAX_CONTENT_LENGTH];
    int total = sizeof(response) - 1;
    sent = 0;
    std::string message = "GET " + route + "HTTP/1.1" + "\r\n\r\n";
    do
    {
        bytes = write(sockfd, message.c_str() + sent, total - sent);
        if (bytes < 0) error("!!!! ERROR writing message to socket");
        if (bytes == 0) break;
        sent += bytes;
    } while (sent < total);

    std::cout << ">>>> Request sent: \n" << message << std::endl;

    // ---- Receive the response byte by byte
    memset(response, 0, sizeof(response));
    total = sizeof(response) - 1;
    received = 0;
    do {
        bytes = read(sockfd, response + received, total - received);
        if (bytes < 0)
            error("!!!! ERROR reading response from socket");
        if (bytes == 0)
            break;
        received += bytes;
    } while (received < total);

    if (received == total)
        error("!!!! ERROR storing complete response from socket (not enough space allocated)");
  • TLDR:我是否将正确的字符数组发送到服务器? 截至目前,它具有以下格式: "GET /route HTTP/1.1\\r\\n\\r\\n" 我是否忘记了让服务器知道这是 GET 请求的任何标头/其他信息?
>>>> Request sent:
GET /links HTTP/1.1

这不是有效的 HTTP 请求。 它缺少带有目标域名的 Host 标头,即它至少应该是这样的

GET /links HTTP/1.1
Host: www.example.com

除此之外,您的代码只是尝试读取数据,直到服务器关闭连接或达到内部缓冲区的大小。 但是 HTTP/1.1 默认使用持久连接。 因此,服务器可能会在响应发送后简单地保持连接打开,因为它期待您的下一个请求,这意味着您的程序将简单地阻止什么都不做。

请注意,HTTP 远比看起来复杂。 如果您想实现它而不是使用现有库,请研究实际标准 这就是标准的用途。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM