Python TCP Socket服务端无法接收客户端数据问题求助
Python Socket TCP 服务端无法接收客户端回传数据的解决方案
问题原因
- 核心原因:TCP是面向流的传输协议,本身没有数据边界,现有服务端接收逻辑依赖
recv返回空值作为结束标识,但该标识只有在连接被主动关闭时才会触发。当前客户端发送完命令执行结果后并未关闭连接,而是继续等待下一条指令,导致服务端永远阻塞在recv调用,无法结束接收循环。 - 次要问题:服务端代码逻辑存在冗余,开头要求用户输入监听IP,但实际
bind操作写死了localhost,输入的IP参数完全未生效,无法支持跨设备客户端连接。 - 潜在风险:客户端未处理服务端断开连接的场景,当服务端主动关闭连接后,客户端会进入死循环持续执行空命令。
修复方案
采用长度前缀法解决TCP数据边界问题:客户端发送数据前先发送4字节的大端格式数据长度,服务端先读取长度再按长度接收完整数据,无需依赖连接断开判断结束。
修复后服务端代码
import socket from colorama import Fore import struct # 用于处理长度前缀的打包解包 ip = input(f"{Fore.GREEN}Enter your ip addr\n{Fore.YELLOW}!\t$ ") print(Fore.BLUE, 'The server is running on port number 8080') s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind((ip,8080)) # 改为使用用户输入的IP s.listen(5) conn, addr = s.accept() print(Fore.RED, 'connection ready') while True: cmd = input("Enter your cmd>>") if cmd == "": continue # 直接跳过空输入优化逻辑 conn.sendall(cmd.encode('utf-8')) # 先读取4字节的长度前缀 len_data = b"" while len(len_data) < 4: chunk = conn.recv(4 - len(len_data)) if not chunk: conn.close() exit("客户端断开连接") len_data += chunk data_len = struct.unpack('!I', len_data)[0] # 按长度读取完整数据 data = b"" while len(data) < data_len: resp = conn.recv(min(1024, data_len - len(data))) if not resp: break data += resp print(Fore.GREEN, data.decode())
修复后客户端代码
import socket, os import struct # 用于处理长度前缀的打包解包 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 如果连接远程服务端,将localhost改为服务端实际IP s.connect(("localhost", 8080)) while True: SerData = s.recv(1024).decode() if not SerData: # 处理服务端断开的情况 s.close() break CliData = os.popen(SerData) CliData = CliData.buffer.read() # 先打包数据长度为4字节大端整数再发送 len_prefix = struct.pack('!I', len(CliData)) s.sendall(len_prefix) s.sendall(CliData)
测试说明
- 本地测试时服务端输入IP填写
127.0.0.1即可 - 跨设备测试需要服务端填写本机局域网/公网IP,同时放开防火墙8080端口的入站规则
内容的提问来源于stack exchange,提问作者asaduzzaman asad
相关产品推荐
相关产品推荐

