用socket发GET请求核心三步:建连(解析域名+连接)、发合规HTTP/1.1请求头(含Host、双\r\n结尾)、收完整响应(按Content-Length或chunked解析)。需注意Winsock初始化、TCP流式读取及错误处理。

用 socket 发送 GET 请求,核心就三步:建连、发请求、收响应
直接调 connect 到目标服务器的 80 端口(或 443 + TLS),拼一个合法的 HTTP/1.1 GET 请求头,send 出去,再用 recv 循环读直到断连或超时。不需要第三方库,但必须手动处理换行、\r\n、Content-Length 或分块传输的边界。
常见错误是忘记末尾两个 \r\n,导致服务器不返回;或没处理响应体长度,recv 卡住;还有把域名当 IP 直接连——得先调 getaddrinfo 解析。
-
getaddrinfo是跨平台解析域名的唯一靠谱方式,别手写inet_addr或硬编码 IP - HTTP 请求头必须含
Host:字段,否则 HTTP/1.1 服务器大概率返回 400 - 发完请求后,别立刻
close,要等服务器主动 FIN,或自己按Content-Length/Transfer-Encoding: chunked规则收完
如何安全读取完整 HTTP 响应体
服务器不会等你慢慢 recv,它发完就关连接,或按 chunked 编码分段发。所以不能只调一次 recv 就完事。
最简方案:先读响应头(直到遇到空行 \r\n\r\n),从中提取 Content-Length: 值;若不存在,且看到 Transfer-Encoding: chunked,就得实现 chunked 解码逻辑;否则就一直读到对端 recv 返回 0(即 FIN)。
立即学习“C++免费学习笔记(深入)”;
- 用
std::string动态拼响应,避免固定缓冲区溢出 - 每次
recv前检查返回值:-1 表示错误(查errno),0 表示连接关闭 - 别假设一次
recv能拿到整个响应头——TCP 是流式协议,可能只来几个字节
GET 请求字符串怎么拼才不被 400 拦住
一个最小可用的 GET 请求不是 "GET / HTTP/1.1" 就完事,缺字段、格式错、少换行都会让服务器拒收。
标准写法必须包含:
- 首行:
GET /path HTTP/1.1\r\n - 必需头:
Host: example.com\r\n(注意:不带http://,也不含端口,除非是非标端口) - 可选但推荐:
Connection: close\r\n(省得你处理 keep-alive) - 结尾:
\r\n(即空行,表示头部结束)
例如请求 http://httpbin.org/get,Host 应为 httpbin.org,路径为 /get,拼出来就是:
GET /get HTTP/1.1\r\nHost: httpbin.org\r\nConnection: close\r\n\r\n
Windows 下编译运行前必须初始化 Winsock
Linux/macOS 直接调 socket 就行,Windows 必须先调 WSAStartup,否则所有 socket 函数都返回失败。
漏掉这步,socket() 返回 INVALID_SOCKET,WSAGetLastError() 是 10093(WSANOTINITIALISED)——这个错误码很多人搜不到原因。
- 初始化只需一次:
WSAData wsa; WSAStartup(MAKEWORD(2,2), &wsa); - 程序退出前记得
WSACleanup() - 别在子线程里重复初始化,也别在没初始化时调任何 socket 函数
跨平台代码建议用宏包裹:#ifdef _WIN32 里做初始化,其他平台跳过。真正容易被忽略的是:即使你只在 Linux 上测试,一旦有人拿你的代码去 Windows 编译,第一行 socket 就崩,而且错误信息毫无提示性。


















