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

Winsock极简HTTP服务器半数请求报ERR_CONNECTION_ABORTED原因

问题描述

我尝试在Windows平台编写一个极简HTTP服务器,通过Chrome访问http://127.0.0.1:5000查看响应。下述代码有时可正常返回"Hello World",但半数场景下请求会失败,Chrome抛出ERR_CONNECTION_ABORTED错误,即便重启服务器问题仍复现,需要定位故障原因。

错误截图:
错误截图

问题代码:

#include <winsock2.h>
#include <iostream>
#pragma comment(lib, "ws2_32.lib")
int main()
{
    WSADATA WSAData;
    SOCKET sock, csock;
    SOCKADDR_IN sin, csin;
    WSAStartup(MAKEWORD(2,0), &WSAData);
    sock = socket(AF_INET, SOCK_STREAM, 0);
    sin.sin_addr.s_addr = INADDR_ANY;
    sin.sin_family = AF_INET;
    sin.sin_port = htons(5000);
    bind(sock, (SOCKADDR *) &sin, sizeof(sin));
    listen(sock, 0);
    while(1)
    {
        int sinsize = sizeof(csin);
        if((csock = accept(sock, (SOCKADDR *) &csin, &sinsize)) != INVALID_SOCKET)
        {
            std::string response = "HTTP/1.1 200 OK\nConnection: close\nContent-Length: 11\n\nHello World";
            send(csock, response.c_str(), response.size(), 0);
            std::cout << "done";
            closesocket(csock);
        }
    }
    return 0;
}
故障原因

核心问题是连接关闭逻辑不符合TCP和HTTP规范,具体触发点如下:

  • 代码接受连接后完全不读取客户端发送的HTTP请求,直接发送响应就调用closesocket。此时socket接收缓冲区里还存着浏览器发来的未读请求数据,Windows内核会直接丢弃这些未读数据,向客户端发送RST重置包而非走正常的TCP四次挥手流程。Chrome收到RST包就会直接中断连接,抛出ERR_CONNECTION_ABORTED错误。偶发成功纯粹是时序巧合:如果浏览器刚好在接收到RST前读完了完整响应,就会显示内容,否则直接报错。
  • HTTP响应头使用\n作为换行符,不符合HTTP协议要求的\r\n(CRLF)换行规范,浏览器严格解析模式下会判定响应非法。
  • listen函数的backlog参数设为0,Windows下该配置会让待处理连接队列长度极小,Chrome访问页面时通常会并行发起页面请求、favicon请求等多个连接,队列满后新连接会被直接拒绝,进一步提升故障概率。
修复方案

按以下点调整代码即可解决问题:

  1. 发送响应前,先循环调用recv读取客户端请求,直到读到\r\n\r\n标记(HTTP请求头结束标识),确认请求接收完成。
  2. 将响应头里的所有换行符从\n替换为\r\n,符合HTTP协议规范。
  3. 发送完响应后,先调用shutdown(csock, SD_SEND)触发TCP优雅关闭,等待客户端确认收到所有数据后,再调用closesocket关闭连接,避免内核发送RST包。
  4. 将listen的第二个参数(连接队列长度)调整为合理值,比如10。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 08:06:19