Socket中解码POST请求失败及返回200响应无效的问题排查
问题根源与解决方案
核心问题解析
UnicodeDecodeError 原因
你收到的二进制数据是TLS握手数据包(开头的\x16\x03是TLS握手标识:0x16代表握手类型,0x03代表SSL/TLS版本),说明Postman用HTTPS协议请求你的5050端口,但你的socket是纯TCP服务,未做SSL/TLS加密处理,加密数据自然无法用UTF-8或ASCII解码。200响应无效原因
Postman在HTTPS模式下会先发起TLS握手,你的socket直接发送HTTP响应时,客户端还在等待握手完成,根本不会处理这个响应;另外即使是HTTP请求,你的响应缺少必要的HTTP头部(比如Content-Length),也会导致Postman无法正确识别响应结束。
解决方案
方案1:改用HTTP协议通信(快速测试)
修改Postman请求为http://localhost:5050(禁用HTTPS),同时修正代码以正确处理HTTP请求和JSON解析:
import socket import json print("Status: ON") # 将socket初始化逻辑放到循环外,避免重复创建 with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind(("", 5050)) s.listen() while True: conn, addr = s.accept() print("Connected by ", "IP -", addr[0], "PORT -", addr[1]) with conn: # 读取完整HTTP请求(简单实现,仅适用于测试场景) received_data = b"" while b"\r\n\r\n" not in received_data: chunk = conn.recv(2048) if not chunk: break received_data += chunk # 解析POST请求中的JSON体 if b"POST" in received_data: header_end = received_data.find(b"\r\n\r\n") if header_end != -1: body = received_data[header_end+4:] try: json_data = json.loads(body.decode("utf-8")) print("Parsed JSON:", json_data) except json.JSONDecodeError as e: print("Invalid JSON:", e) else: print("No request body found") # 发送标准HTTP 200响应 response = b"HTTP/1.1 200 OK\r\n" response += b"Content-Type: application/json\r\n" response += b"Content-Length: 0\r\n" response += b"\r\n" conn.sendall(response)
方案2:支持HTTPS协议(需SSL证书)
如果必须用HTTPS,需用ssl模块包装socket,同时准备SSL证书(可生成自签名证书测试):
import socket import ssl import json print("Status: ON") # 生成自签名证书(终端执行): # openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind(("", 5050)) s.listen() # 用SSL包装socket context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) context.load_cert_chain(certfile="cert.pem", keyfile="key.pem") with context.wrap_socket(s, server_side=True) as ssock: while True: conn, addr = ssock.accept() print("Connected by ", "IP -", addr[0], "PORT -", addr[1]) with conn: received_data = b"" while b"\r\n\r\n" not in received_data: chunk = conn.recv(2048) if not chunk: break received_data += chunk # 解析JSON请求体 if b"POST" in received_data: header_end = received_data.find(b"\r\n\r\n") if header_end != -1: body = received_data[header_end+4:] try: json_data = json.loads(body.decode("utf-8")) print("Parsed JSON:", json_data) except json.JSONDecodeError as e: print("Invalid JSON:", e) # 发送HTTPS响应 response = b"HTTP/1.1 200 OK\r\n" response += b"Content-Type: application/json\r\n" response += b"Content-Length: 0\r\n" response += b"\r\n" conn.sendall(response)
测试注意事项
- 方案1测试时,Postman必须选HTTP协议,URL填
http://localhost:5050,请求方法选POST,Body选raw/JSON格式输入测试数据。 - 方案2测试时,Postman选HTTPS协议,若用自签名证书,需在Postman设置中关闭SSL证书验证(Settings -> General -> SSL certificate verification 设为Off)。
内容的提问来源于stack exchange,提问作者PythonBeginingEnjoyer
相关产品推荐
相关产品推荐

