Python Socket通讯时客户端发Hello服务端打印连续重复字符串问题求解
问题原因
- 核心是TCP粘包问题:TCP是面向流的传输协议,本身没有内置消息边界,传输过程中会将多个小数据包合并为一个大数据块收发。你的客户端死循环无间隔发送
"Hello"字符串,服务端调用recv(1024)时会一次性读取套接字缓冲区中所有可用数据,自然就把多个Hello拼接在一起输出。 - 服务端逻辑存在缺陷:现有代码外层循环只在新连接建立时读取一次数据,之后就回到
accept状态等待新连接,现有连接后续发送的所有数据都不会被处理,你现在看到的一长串Hello就是连接建立后客户端已经发送到缓冲区的所有数据被一次性读取的结果。
修复方案
解决思路是先修复服务端持续读取的逻辑,再通过约定消息边界解决粘包问题,这里用最容易实现的换行符作为消息边界:
修改后的client.py
每个消息末尾加换行符标记边界:
import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(("192.168.0.108",1234)) while True: s.send(bytes("Hello\n","utf-8"))
修改后的server.py
将套接字包装为文件对象按行读取,同时支持持续读取单连接的消息:
import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 开启端口复用,避免程序重启时报端口占用错误 s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind(("0.0.0.0",1234)) s.listen(100) while True: clientsocket, addr= s.accept() # 把套接字包装为UTF-8编码的读文件对象,自动处理字节解码和按行拆分 reader = clientsocket.makefile('r', encoding='utf-8') while True: line = reader.readline() if not line: # 读取结果为空说明连接已断开,退出循环释放资源 break msg = line.strip() print(msg) clientsocket.close()
如果不想用文件对象包装,也可以自己维护接收缓冲区,每次recv之后按约定的分隔符拆分消息,剩余未拆分的内容留到下一次读取后合并处理即可。
内容的提问来源于stack exchange,提问作者Shashankh_
相关产品推荐
相关产品推荐

