如何从recv()缓冲区提取HTTP状态码(不可使用http库)
实现方案
核心原理
HTTP响应的结构有固定RFC规范,第一行也就是状态行的格式严格为HTTP/版本号 状态码 原因短语,行与行之间用\r\n作为分隔符,整个状态行全部由ASCII字符组成,完全不需要依赖任何HTTP解析库,纯靠字节查找、字符串切割就能拿到状态码。
提取步骤
- 从接收到的字节缓冲区中,定位第一个换行分隔符(优先匹配标准的
\r\n,兼容部分服务器使用的纯\n换行),切出分隔符之前的部分,就是完整的状态行 - 对切出来的状态行做空格分割,第二个元素就是数字格式的状态码
- 按照状态码值写对应的分支处理逻辑即可
适配修改后的完整代码
from socket import * #constants variables target_host = 'localhost' target_port = 80 target_dir = 'dashboard/index.html' # create a socket object client = socket(AF_INET, SOCK_STREAM) # create an INET (IPv4), STREAMing socket (TCP) # connect the client client.connect((target_host,target_port)) # send some data request = "GET /%s HTTP/1.1\r\nHost:%s\r\n\r\n" % (target_dir, target_host) client.send(request.encode()) # receive some data data = b'' while True: buffer = client.recv(2048) if not buffer: break data += buffer client.close() # ---------------- 无依赖提取状态码逻辑 ---------------- # 定位状态行的结束位置 crlf_pos = data.find(b'\r\n') # 兼容纯LF换行的非标准实现 if crlf_pos == -1: crlf_pos = data.find(b'\n') if crlf_pos == -1: print("收到的响应不是合法HTTP格式") else: # 状态行全部为ASCII字符,单独解码不会受后续响应体二进制内容影响 status_line = data[:crlf_pos].decode('ascii') # 按空格拆分状态行,第二个字段为状态码 status_code = int(status_line.split(' ')[1]) # 按状态码执行对应逻辑 if status_code == 200: print("ok") elif status_code == 404: print("页面不存在") elif status_code == 500: print("服务器内部错误") else: print(f"未处理的响应状态码:{status_code}")
关键注意点
- 整个实现没有导入任何
http相关模块,完全靠原生socket返回的字节流解析,符合要求 - 仅单独解码状态行(ASCII编码段),不对全量响应数据做utf-8解码,避免响应体包含二进制内容时触发解码错误
- 可优化的点:不需要等待整个响应体全部接收完成,只要recv拿到的缓冲区中已经包含第一个换行分隔符,就可以提前提取状态码执行逻辑,大体积响应时能大幅减少等待时间
内容的提问来源于stack exchange,提问作者michael ferreira
相关产品推荐
相关产品推荐

