

新闻资讯
技术学院监听端口前需设socket为非阻塞或用select/poll避免accept阻塞;bind前须setsockopt启用SO_REUSEADDR;HTTP解析须按\r\n切分、状态机处理TCP流式数据;响应必须严格遵循HTTP格式,含正确Content-Length与\r\n分隔。
socket 监听端口前必须设为非阻塞或正确处理 accept 阻塞默认 socket 是阻塞的,accept() 会卡住主线程,无法响应其他连接或做请求解析。不加处理就写个死循环调 accept,服务器看起来“启动了”,但实际只能服务一个请求,后续连接全被丢弃或超时。
fcntl(sockfd, F_SETFL, O_NONBLOCK)(Linux/macOS)或 ioctlsocket(sockfd, FIONBIO, &nonblocking)(Windows)设为非阻塞select() 或 poll() 等待可读事件,避免忙轮询;简单 demo 可先用阻塞模式 + 多线程,但生产环境必须异步或事件驱动bind() 再 listen(),且 bind() 前要 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)),否则改代码重启时经常报 Address already in use
\r\n 切分,不能只认 \n
HTTP/1.1 规范明确要求行尾是 \r\n(CRLF),不是 Unix 风格的 \n。用 std::getline() 默认按 \n 分割,会导致读到 "GET / HTTP/1.1\r" 这种带残留 \r 的字符串,后续解析路径或方法失败。
"\r\n" 位置比依赖 std::getline 更可靠method、path、version,中间用空格分隔;空行(即连续两个 \r\n)标志着 headers 结束recv() 缓冲区当完整请求处理——TCP 是流式协议,一次 recv() 可能只收到半行,也可能包含多个请求,必须缓存 + 状态机解析哪怕只是返回 "Hello World",也要有状态行、Content-Length、空行和正文。少一个 \r\n,或 Content-Length 和实际字节数不符,Chrome/Firefox 就会卡在 loading 状态或显示 ERR_INVALID_HTTP_RESPONSE。
HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 12\r\n\r\nHello World\r\n
Content-Length 值必须是响应体(不含 header)的字节数,不是字符串长度(注意 std::st
ring::length() 对 UTF-8 是字节数,没问题;但若用 wstring 就错)\r\n\r\n 结束 headers,之后紧跟 body;body 后**不要**额外加 \r\n,否则算进 Content-Length 就错Connection: keep-alive 并复用 socket,但简单场景建议每次响应后 close(client_fd),避免连接堆积绑定 80 或 443 端口在 Linux/macOS 需 root 权限,Windows 虽然宽松些但仍有策略限制。强行 sudo 运行 C++ 服务风险高,且和前端开发流程脱节。
8080、8000 或 3000,浏览器访问 http://localhost:8080/ 即可"index.html",先检查请求 path 是否为 "/",再映射到本地文件,注意防御性过滤:拒绝 ".."、"%2e%2e" 等目录遍历尝试