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

使用Python Socket获取HTTP请求响应体失败的问题排查

问题:使用socket模块获取Flask应用的GET响应仅得到响应头,无法获取响应体

我尝试使用socket模块获取GET请求的响应体,但即使设置了较大的缓冲区大小,也仅能获取到响应头。我访问的Web应用是自己使用Flask搭建的。

sockets.py

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("localhost", 5000))
s.sendall(b'GET / HTTP/1.1\r\nHost:127.0.0.1\r\n\r\n')
print(s.recv(4096).decode('utf-8'))

app.py

from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def main():
    return render_template('main.html')

main.html

<html>
    <body>
        <h1>Hello world</h1>
    </body>
</html>

执行sockets.py后得到的结果如下:

HTTP/1.1 200 OK
Server: Werkzeug/2.1.2 Python/3.10.5  
Date: Sun, 07 Aug 2022 18:33:53 GMT   
Content-Type: text/html; charset=utf-8
Content-Length: 66
Connection: close

如你所见,我没有获取到响应体。请问我哪里操作出错了?


解决方法

你的问题出在只调用了一次s.recv()。TCP是流式协议,数据不会保证一次性全部到达,哪怕你设置了足够大的缓冲区,服务器可能分批次发送数据,第一次recv可能只接收到了响应头部分,剩下的响应体还在传输通道中。

从响应头的Content-Length: 66可以看到,响应体的长度是66字节,你可以通过循环调用recv来获取完整的响应内容。

方法一:循环接收直到数据传输完成

修改后的sockets.py代码如下:

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("localhost", 5000))
s.sendall(b'GET / HTTP/1.1\r\nHost:127.0.0.1\r\n\r\n')

# 循环接收所有数据
full_response = b''
while True:
    chunk = s.recv(4096)
    if not chunk:  # 连接关闭时,recv返回空字节串
        break
    full_response += chunk

# 解码并输出完整响应
print(full_response.decode('utf-8'))

方法二:解析响应头后精确接收响应体

如果需要更严谨地处理,可以先解析响应头拿到Content-Length,再精确读取对应长度的响应体:

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("localhost", 5000))
s.sendall(b'GET / HTTP/1.1\r\nHost:127.0.0.1\r\n\r\n')

# 先接收完整的响应头(直到\r\n\r\n分隔符)
response_header = b''
while b'\r\n\r\n' not in response_header:
    response_header += s.recv(1)

# 解析Content-Length的值
header_content = response_header.decode('utf-8')
content_length = int([line for line in header_content.split('\r\n') if line.startswith('Content-Length')][0].split(': ')[1])

# 接收指定长度的响应体
response_body = s.recv(content_length)

# 输出完整的响应内容
print(header_content + response_body.decode('utf-8'))

这两种方式都能获取到包含响应体的完整HTTP响应。核心原因是必须通过循环调用recv来处理TCP流式数据的分批传输问题,不能依赖单次recv获取全部内容。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 15:36:18