Python新手求助:流式Socket服务器循环无法接收后续数据包问题
问题分析与修复方案
嘿,我一眼就瞅出你代码里的问题啦——你把sock.accept()放在了while循环的最外层,这就导致程序每次处理完一个数据包后,就又回到等待新连接的状态,完全忽略了同一个客户端的后续数据包!
核心问题拆解
原来的逻辑是:
- 进入while循环
- 等待新客户端连接(
sock.accept()) - 接收一次数据
- 处理数据
- 回到循环开头,再次等待新连接
这就意味着,同一个客户端发的第二个、第三个数据包,程序根本没机会处理,因为它一直卡在accept()那里等新的连接进来。
修复后的代码
我们需要把accept()拿到外层循环,先建立好连接,然后在内部循环里持续从这个连接接收数据,直到客户端断开,再重新等待新连接:
# Configure TAGP listener import socket import json # 假设TAGPListenerPort和client已经初始化 TAGPListenerPort = 12345 # client = ... 你的ThingsBoard客户端初始化代码 ipaddress = ([l for l in ([ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")][:1], [[(s.connect(('8.8.8.8', 53)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1]]) if l][0][0]) server_name = ipaddress server_address = (server_name, TAGPListenerPort) print ('starting TAGP listener on %s port %s' % server_address) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(server_address) sock.listen(1) sensor_data = {'tag': 0} # Listen for TAGP data and forward events to ThingsBoard try: while True: print("Waiting for a new connection...") # 只在需要新连接时调用accept() connection, client_address = sock.accept() print(f"Connected from {client_address}") try: # 内部循环持续接收同一个客户端的数据包 while True: # 用decode处理字节串,避免str(b'xxx')带来的b''前缀问题 data = connection.recv(1024).decode('utf-8', errors='ignore') # 如果recv返回空字符串,说明客户端断开连接 if not data: print(f"Client {client_address} disconnected") break if "EVNTTAG" in data: timestamp = ((data.split())[1])[:17] tag = ((data.split())[1])[17:] sensor_data['tag'] = tag client.publish('v1/devices/me/telemetry', json.dumps(sensor_data), 1) print(f"Received data: {data}") finally: # 不管连接正常断开还是异常,都关闭连接 connection.close() except KeyboardInterrupt: # Close socket server (TAGP) sock.close() # Close client to ThingsBoard client.loop_stop() client.disconnect() print("Server stopped by user")
额外注意事项
- 数据完整性:
recv(1024)只能接收最多1024字节的数据,如果你的数据包超过这个大小,会被截断。可以考虑循环接收直到拿到完整的数据包(比如根据特定分隔符判断)。 - 字节串处理:原代码里
str(connection.recv(1024))会把字节串转成类似b'EVNTTAG...'的字符串,用decode()能得到更干净的文本内容,errors='ignore'可以处理一些非UTF-8的特殊字符。 - 异常处理:内部循环可以加上
except ConnectionResetError之类的异常捕获,避免客户端突然断开导致程序崩溃。
内容的提问来源于stack exchange,提问作者user3065078
相关产品推荐
相关产品推荐

