【问题标题】:Socket connection 301 or 400套接字连接 301 或 400
【发布时间】:2021-01-21 05:17:57
【问题描述】:

我在向我的域发送 GET 时遇到问题。使用 80 端口,我收到 301 永久移动,使用 443 端口,我收到 400 错误请求。当我关闭重定向到 https 时,一切正常。

std::string HttpGet(std::string szHost, std::string szApi) {
    std::string request;
    std::string response;
    int resp_leng;
    char buffer[1024];
    struct sockaddr_in serveraddr;
    int sock;
    WSADATA wsaData;    
    if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) L::Print(XorStr("web_parser: WSAStartup() failed"));
    struct hostent* host;
    host = gethostbyname(szHost.c_str());
    int port = 80;
    request += "GET " + szApi + " HTTP/1.0\r\n";
    request += "Host: " + szHost + "\r\n";
    request += "User-Agent: WebParser [Build: 1.1] \r\n";
    request += "\r\n";
    if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) L::Print(XorStr("web_parser: socket() failed"));
    memset(&serveraddr, 0, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = *((unsigned long*)host->h_addr);
    serveraddr.sin_port = htons((unsigned short)port);
    struct in_addr** addr_list;
    addr_list = (struct in_addr**)host->h_addr_list;
    response = "";
    if (connect(sock, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0)  L::Print(XorStr("web_зarser: connect() failed"));
    if (send(sock, request.c_str(), request.length(), 0) != request.length()) L::Print(XorStr("web_parser: send() sent a different number of bytes than expected"));
    resp_leng = 1024;
    while (resp_leng > 0) {
        resp_leng = recv(sock, (char*)&buffer, 1024, 0);
        if (resp_leng > 0) response += std::string(buffer).substr(0, resp_leng);
    }
    closesocket(sock);
    WSACleanup();

    const char* buf = response.c_str(); // Get HTTP response from URL
    const char* content = strstr(buf, "\r\n\r\n");
    if (content != NULL) {
        content += 4; // Offset by 4 bytes to start of content
    }
    else {
        content = buf; // Didn't find end of header, write out everything
    }

    return content;
}

谢谢。

【问题讨论】:

  • 301 是预期的,因为您已明确添加了从 HTTP 到 HTTPS 的重定向。 400 也是预期的,因为您在需要 HTTPS 时尝试发送纯 HTTP 请求。请注意,HTTPS 不仅仅是一个不同的端口,它是一个不同的协议:HTTP over TLS。
  • 除非这是一种学习体验,否则请考虑使用 HTTP 库,例如 cURL,甚至只是 WinHttp。

标签: c++ sockets https


【解决方案1】:

@Steffen Ullrich 在他的评论中写道,在这种情况下,结果代码 400 和 301 是正确的。

当您尝试连接到端口 80 并且服务器配置为重定向到 https 时,服务器确实尝试重定向到 https 并发送响应“301 Moved Permanently”,标题为“Location: https://....'。在这种情况下,标准响应短语是“永久移动”。一些响应可能会导致重定向。这些响应的代码为 300 - 399,它们被称为“重定向”响应。

当您尝试连接到端口 443 时,通信不会以 HTTP 协议开始,但 SSL/TLS 握手必须在 HTTP 通信开始之前完成,并且 HTTP 通信必须通过 SSL/TLS 会话发送已确立的。您收到 400 Bad Request 是因为您的代码没有尝试进行 SSL/TLS 握手。

有几个选项可以在您的应用程序中支持 SSL/TLS

  • 仅使用套接字 API 从头开始​​实施 SSL/TLS 层。即使对于经验丰富的开发人员来说,这也是一项非常艰巨的任务。也许您可以尝试学习经验,但不要在实际应用中这样做。
  • 使用现有的 SSL/TLS 库,例如 windows 内置的 SSL 内容。见SSL api for winsock?。它比第一个选项更容易,但任务仍然相当复杂。
  • 使用支持 HTTP 和 HTTPS 的库。有很多图书馆。例如微软提供WinHTTP。这是实现 HTTP/HTTPS 客户端的推荐方法,因为它不需要重新发明轮子。

【讨论】:

    猜你喜欢
    • 2017-07-09
    • 1970-01-01
    • 2011-08-15
    • 2013-09-18
    • 2012-02-27
    • 2013-02-02
    • 2011-08-31
    • 1970-01-01
    相关资源
    最近更新 更多