GPS追踪器发送LOAD命令后1分钟出现socket连接被强制关闭问题求助
问题描述
我有若干GPS追踪设备,发送"LOAD"命令后,设备会向服务器发送状态信息,初期一切正常能收到响应,但1分钟后出现错误:
An existing connection was forcibly closed by the remote host
恳请协助解决该问题,以下是我的服务器代码:
import datetime import socket import threading host = "0.0.0.0" port = 4018 connedcted_devices = set() output_imei_list = set() def get_clients(sock, conn): _msg = "LOAD" message = 'message ' + str(_msg) encodedMessage = bytes(message, 'utf-8') output_imei = conn.recv(1024) print(output_imei) if output_imei in output_imei_list: print("Connection already exists") else: output_imei_list.add(output_imei) # print(output_imei_list) connedcted_devices.add(conn) print("New connection added to cnn_list") conn.sendall(encodedMessage) def receive_response(conn): # counter = 0 while True: # if counter == 50 : # break # conn.settimeout(60) # Set timeout to 60 seconds encodedAckText = conn.recv(1024) ackText = encodedAckText.decode('utf-8') splitedTextList = ackText.split(",") list_len = len(splitedTextList) if list_len > 0: print(splitedTextList) # counter += 1 # print(counter) def main(): with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: sock.bind((host, port)) print('socket binded') sock.listen() print('socket now listening') while True: conn, addr = sock.accept() get_clients(sock, conn) if(len(connedcted_devices) > 0): for x in connedcted_devices: threading.Thread(target=receive_response, args=(x,)).start() if __name__ == '__main__': main()
问题根源分析
- 重复创建线程:每次新设备连接时,都会遍历所有已连接设备并启动新的
receive_response线程,同一个连接被多个线程同时调用recv(),引发IO冲突,最终导致连接被强制关闭。 - 未处理连接断开:
receive_response的死循环没有处理recv()返回空字节的情况(客户端断开的标志),线程会持续异常操作,触发连接关闭。 - 无超时机制:注释掉了超时设置,
recv()会一直阻塞,可能触发设备端的超时断开逻辑。 - 拼写错误:
connedcted_devices存在拼写错误,可能导致集合操作异常。
修复后的代码
import datetime import socket import threading host = "0.0.0.0" port = 4018 connected_devices = set() # 修正拼写错误 output_imei_list = set() def handle_client(conn): # 接收设备IMEI output_imei = conn.recv(1024) if not output_imei: conn.close() return print(f"收到设备IMEI: {output_imei}") # 检查设备是否已连接 if output_imei in output_imei_list: print("该设备已存在连接,关闭新连接") conn.close() return else: output_imei_list.add(output_imei) connected_devices.add(conn) print("新设备连接已添加") # 发送LOAD命令 message = 'message LOAD' encodedMessage = bytes(message, 'utf-8') conn.sendall(encodedMessage) # 持续接收设备响应 try: conn.settimeout(60) # 恢复60秒超时,匹配设备端逻辑 while True: encodedAckText = conn.recv(1024) if not encodedAckText: # 客户端主动断开 break ackText = encodedAckText.decode('utf-8').strip() if not ackText: continue splitedTextList = ackText.split(",") print(f"设备响应: {splitedTextList}") except socket.timeout: print(f"设备 {output_imei} 超时无响应,关闭连接") except Exception as e: print(f"处理设备响应时出错: {e}") finally: # 清理资源,避免内存泄漏 if conn in connected_devices: connected_devices.remove(conn) if output_imei in output_imei_list: output_imei_list.remove(output_imei) conn.close() print(f"设备 {output_imei} 连接已关闭") def main(): with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: sock.bind((host, port)) print('Socket已绑定端口') sock.listen() print('Socket开始监听') while True: conn, addr = sock.accept() print(f"收到来自 {addr} 的新连接") # 每个新连接单独启动一个线程,避免重复创建 threading.Thread(target=handle_client, args=(conn,), daemon=True).start() if __name__ == '__main__': main()
关键修改说明
- 合并处理逻辑:把
get_clients和receive_response合并为handle_client,每个连接仅对应一个处理线程,彻底解决多线程IO冲突问题。 - 处理连接断开:检测
recv()返回空字节的情况,及时清理资源并关闭连接。 - 恢复超时机制:设置60秒超时,防止线程无限阻塞,同时兼容设备端的超时逻辑。
- 守护线程设置:启动线程时添加
daemon=True,确保主程序退出时所有子线程自动结束。 - 资源清理:在
finally块中统一移除设备集合中的连接和IMEI,避免内存泄漏。
内容的提问来源于stack exchange,提问作者NEBEZ
相关产品推荐
相关产品推荐

