You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Winsock发送POST请求时send()返回-1及400错误排查求助

问题分析与解决方案

初始代码:send()返回-1的原因

Socket配置错误

  • 客户端不需要调用bind():bind()是服务器端用来绑定本地端口的操作,客户端直接调用connect()连接服务器即可。错误绑定会导致Socket无法正常建立与服务器的连接,send()自然失败。
  • 未调用connect():创建Socket后没有连接到目标服务器,处于未连接状态的Socket无法发送数据。
  • 端口设置错误:代码中用了54000端口,若服务器未使用该端口,会导致连接失败。默认HTTP用80端口,HTTPS用443端口。
  • 缺乏错误检查:socket()、gethostbyname()的返回值未做校验,比如gethostbyname()失败返回NULL时,直接访问host->h_addr会引发崩溃。

POST请求格式错误

  • 请求行路径错误:HTTP请求行的路径部分只需写相对于域名的路径,正确格式应为POST /script.php HTTP/1.1,而非POST stuff://domain.net/script.php? HTTP/1.1。
  • 换行符不符合HTTP规范:HTTP协议要求所有头字段和空行必须用\r\n(CRLF)分隔,代码中用单独的\n会导致请求格式不被服务器识别。

更新后代码:400 Bad Request的原因

核心错误:HTTPS连接未做TLS握手

代码注释提到stuff is https且用了443端口,但直接通过普通TCP Socket发送明文HTTP请求。HTTPS要求先建立TLS/SSL加密会话,服务器收到非TLS握手数据时会返回400错误。

请求格式仍有问题

  • 请求行路径错误:依然保留了stuff://domain.net/script.php的错误格式,正确路径应为/script.php。
  • 换行符可能仍不规范:代码中的换行如果还是用单独的\n,会导致请求头格式错误。

其他潜在问题

  • socket_create_http()失败时无有效返回值:若connect()失败,函数未返回INVALID_SOCKET,会导致sock_http为未初始化的垃圾值。
  • 接收响应不完整:仅调用一次recv(),无法保证接收完服务器的全部响应数据。
  • 过时函数使用:gethostbyname()已被淘汰,建议用getaddrinfo()替代,支持IPv6和更可靠的域名解析。

修正步骤

  1. 处理HTTPS连接:
    Windows平台可使用系统自带的Schannel库,或第三方库如OpenSSL,在TCP连接成功后建立SSL/TLS会话,通过SSL套接字发送接收数据,不能直接用普通TCP Socket发送明文请求到443端口。

  2. 修正请求格式:
    正确的POST请求格式示例:

    request << "POST /script.php HTTP/1.1\r\n";
    request << "Host: domain.net\r\n";
    request << "Content-Length: " << data.size() << "\r\n";
    request << "Content-Type: application/x-www-form-urlencoded\r\n";
    request << "Connection: close\r\n";
    request << "\r\n"; // 头与正文的分隔空行
    request << data;
    
  3. 完善Socket错误处理:

    • socket_create_http()函数在任何步骤失败时返回INVALID_SOCKET,main()中检查返回值:
      SOCKET socket_create_http(const char* hostname, unsigned short port)
      {
          struct addrinfo hints = {}, *result;
          hints.ai_family = AF_INET;
          hints.ai_socktype = SOCK_STREAM;
          hints.ai_protocol = IPPROTO_TCP;
      
          int res = getaddrinfo(hostname, nullptr, &hints, &result);
          if (res != 0) return INVALID_SOCKET;
      
          SOCKET sock = INVALID_SOCKET;
          for (struct addrinfo* ptr = result; ptr != nullptr; ptr = ptr->ai_next)
          {
              sock = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
              if (sock == INVALID_SOCKET) continue;
      
              if (connect(sock, ptr->ai_addr, (int)ptr->ai_addrlen) != SOCKET_ERROR)
              {
                  break;
              }
      
              closesocket(sock);
              sock = INVALID_SOCKET;
          }
      
          freeaddrinfo(result);
          return sock;
      }
      
  4. 循环接收完整响应:

    string full_response;
    char buffer[4096];
    int bytes_received;
    while ((bytes_received = recv(sock_http, buffer, sizeof(buffer), 0)) > 0)
    {
        full_response.append(buffer, bytes_received);
    }
    cout << full_response << endl;
    

内容的提问来源于stack exchange,提问作者user19747167

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 12:54:23