MicroPython ESP8266 HTTP服务器请求被截断为536字节问题求助
问题解决方案
根本原因
你遇到的截断问题是ESP8266 MicroPython的正常特性:socket.recv() 单次调用只会返回当前网卡缓冲区中已到达的数据,最大长度受底层MTU限制,默认约为536字节。桌面端Python因为socket缓冲区更大、网络延迟更低,单次调用就能拿到完整请求,所以运行正常,但该逻辑在资源受限的ESP8266上不适用。
具体解决方法
通过分阶段循环接收的逻辑读取完整HTTP请求,操作步骤如下:
- 客户端连接建立后,先给socket设置合理的超时时间,避免无意义阻塞,通常设置1-3秒即可
- 第一阶段先接收请求头,直到读到请求头结束标识
\r\n\r\n,从请求头中解析出Content-Length字段,该值就是POST请求体的总长度 - 第二阶段如果是POST请求,按照解析到的
Content-Length值继续循环接收,直到拿到完整的请求体就停止,不需要等待连接断开
可直接复用的接收函数代码
def read_full_request(conn): # 设置2秒超时,避免长时间卡住 conn.settimeout(2) buffer = b'' # 第一阶段:读取完整请求头 while b'\r\n\r\n' not in buffer: try: chunk = conn.recv(128) if not chunk: break buffer += chunk except OSError: # 超时代表没有更多新的请求头数据 break # 解析请求体长度 content_length = 0 headers_part = buffer.split(b'\r\n\r\n')[0].decode('utf-8', errors='ignore') for line in headers_part.split('\r\n'): if line.lower().startswith('content-length:'): try: content_length = int(line.split(':', 1)[1].strip()) except: content_length = 0 break # 第二阶段:读取完整请求体 if content_length > 0: # 计算已经附带在buffer里的请求体长度 already_read_body = len(buffer) - buffer.find(b'\r\n\r\n') - 4 remaining = content_length - already_read_body while remaining > 0: try: chunk = conn.recv(min(remaining, 128)) if not chunk: break buffer += chunk remaining -= len(chunk) except OSError: break return buffer
原代码修改方法
把你最小复现代码里的:
raw_request = client_server_connection.recv(4096)
替换为:
raw_request = read_full_request(client_server_connection)
即可拿到完整的HTTP请求数据。
注意事项
- 单次接收的chunk大小不要设置太大,128-256字节即可,避免占用ESP8266有限的运行内存
- 不需要再用类文件对象的逐行读取逻辑,该逻辑如果没有匹配到结束条件很容易触发永久阻塞,按Content-Length读取是最稳妥的方案
内容的提问来源于stack exchange,提问作者joshuai96
相关产品推荐
相关产品推荐

