Python3树莓派TCP服务器处理多台Mbed微控制器连接问题咨询
问题核心原因
你现有代码的多线程逻辑存在致命缺陷,是问题的根本诱因:
- 连接对象全局共享:主循环
accept得到的conn连接对象没有传入对应的ClientThread实例,所有线程的run方法都在调用全局conn变量,新连接接入时全局conn会被覆盖,老线程会读到错误连接的数据、出现读写冲突,直接导致只随机响应一台设备、丢包、数据解析错误。 - 未处理TCP粘包/半包问题:TCP是流协议,
conn.recv(64)仅返回当前缓冲区已有的数据,不一定能一次收齐完整数据包,直接按固定长度解析必然触发索引越界。 - 线程内调用的
ip是全局变量,而非存在self.ip中的实例属性,日志打印也会出现错乱。
1. 当前实现方式是否支持同时接收多路消息?
修复代码缺陷后完全可以支持,不需要修改整体多线程架构,修复后参考代码如下:
import sys import socket from threading import Thread class ClientThread(Thread): def __init__(self, conn, ip, port): Thread.__init__(self) self.conn = conn self.ip = ip self.port = port print(f"[+] New server socket thread started for {ip}:{str(port)}") def run(self): # 缓存未处理的剩余数据 buffer = b'' while True: chunk = self.conn.recv(64) if not chunk: # 连接断开退出线程 print(f"[-] Connection closed from {self.ip}:{str(self.port)}") break buffer += chunk if self.ip == '192.168.1.45': # 按GPS设备实际包长调整判断逻辑即可 print("hello GPS") buffer = b'' elif self.ip == '192.168.1.253': # 振动设备单包长24字节,收够后再解析 while len(buffer) >= 24: data = buffer[:24] buffer = buffer[24:] time = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | (data[3]) vibes = [0]*10 for i in range(0, 10): vibes[i] = data[(i*2)+4] << 8 | data[(i*2)+5] print(f"Server received from {self.ip} data: {time} {' '.join(map(str, vibes))}") TCP_IP = '0.0.0.0' TCP_PORT = 80 tcpServer = socket.socket(socket.AF_INET, socket.SOCK_STREAM) tcpServer.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) tcpServer.bind((TCP_IP, TCP_PORT)) # listen只需调用一次,不要放在循环内 tcpServer.listen(4) threads = [] while True: print("Multithreaded Python server : Waiting for connections from TCP clients...") (conn, (ip,port)) = tcpServer.accept() newthread = ClientThread(conn, ip, port) newthread.start() threads.append(newthread)
2. 是否需要对客户端做同步处理避免同时发送数据?
不需要。TCP每个连接的缓冲区是独立的,多客户端同时发送数据不会互相干扰,只要服务端为每个连接分配独立线程处理就不会出现冲突。
3. 不同客户端分配独立端口的方案是否更优?
没有必要,反而会增加设备侧的配置复杂度。你当前使用的单端口多线程方案本身适配你的业务场景,只要修复上述代码缺陷就可以稳定运行。仅当不同客户端的业务逻辑差异极大、需要独立端口权限控制时才需要考虑多端口部署,你的场景不需要做额外调整。
内容的提问来源于stack exchange,提问作者ericleal
相关产品推荐
相关产品推荐

