Python Socket客户端重启PCB后自动重连报错问题咨询
TCP通信中PCB重启后自动重连的问题解决
我负责的项目需要通过TCP连接与外部IO-Module PCB通信,本质是GUI与嵌入式系统交互。现在要实现一个功能:发送命令让PCB重启,重启完成后自动重新建立TCP连接。
调用socket.close()关闭连接后,复用原connect()函数重连时触发错误:
AttributeError: 'socket' object has no attribute 'socket'
问题代码
import socket import time global socket def connect(): global socket connected = 0 socket = socket.socket() try: socket.bind(("192.168.0.10", 2333)) except: print("connection failed") else: print("connecting") for x in range(0, 2): if connected == 0: adress = '192.168.0.240' server_address = (adress, 2333) print('starting up on {} port {}'.format(*server_address)) try: socket.connect(server_address) except: print("trying again") else: print("connection successfully established") connected = 1 if connected == 0: print("connection failed") def reboot_signal(): filler_byte = 0 reboot = 1 checksum = 1 socket.send(bytes([filler_byte, checksum, filler_byte, reboot, filler_byte,filler_byte ,filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte, filler_byte,filler_byte])) def reboot_PCB(): global socket reboot_signal() # dont worry about this, this is essentially just a TCP signal, rebooting the PCB I am communicating with print('rebooting') socket.close() time.sleep(10) # Now I am giving the PCB some time to reboot connect() # now i want to re-connect connect() time.sleep(5) # Now I am giving the PCB some time to reboot a = 1 #my alternative way of making and endless loop while( a == 1): reboot_PCB()
问题分析
- 全局变量命名冲突:导入的
socket模块被同名全局变量覆盖。第一次调用connect()时,socket = socket.socket()将全局的socket从模块对象替换为socket实例;第二次调用connect()时,socket.socket()变成调用实例的socket属性,而socket对象无此属性,直接报错。 - 客户端逻辑错误:TCP客户端不需要调用
bind(),该操作是服务器端绑定端口用的,强行绑定本地端口可能导致重连时端口被占用,连接失败。
解决方案
核心修正点
- 重命名全局socket变量,避免与模块名冲突
- 移除客户端的
bind()操作,遵循TCP客户端标准逻辑 - 增加错误捕获与状态判断,提升代码健壮性
- 优化重连重试逻辑,提升连接成功率
修正后代码
import socket import time # 重命名全局变量,避免与socket模块冲突 client_socket = None def connect(): global client_socket connected = 0 server_address = ('192.168.0.240', 2333) # 客户端无需bind,直接创建socket并尝试连接 client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) print(f'尝试连接到 {server_address[0]} 端口 {server_address[1]}') for retry in range(2): if not connected: try: client_socket.connect(server_address) except Exception as e: print(f'连接失败,重试中... 错误: {str(e)}') time.sleep(1) # 重试前短暂等待 else: print('连接成功建立') connected = 1 if not connected: print('最终连接失败') # 连接失败时关闭socket释放资源 client_socket.close() client_socket = None def reboot_signal(): if client_socket is None: print('未建立连接,无法发送重启信号') return filler_byte = 0 reboot = 1 checksum = 1 # 构造重启指令字节数组,简化写法 reboot_cmd = [filler_byte, checksum, filler_byte, reboot] + [filler_byte] * 124 try: client_socket.send(bytes(reboot_cmd)) except Exception as e: print(f'发送重启信号失败: {str(e)}') def reboot_PCB(): global client_socket reboot_signal() print('正在重启PCB...') # 确保socket存在再关闭,避免空对象操作 if client_socket is not None: try: client_socket.close() except: pass client_socket = None # 等待PCB重启完成,可根据实际情况调整时长 time.sleep(10) # 尝试重新连接 connect() # 初始连接 connect() # 等待初始连接稳定 time.sleep(5) # 循环测试重启重连功能 while True: reboot_PCB() # 增加间隔避免频繁操作 time.sleep(30)
内容的提问来源于stack exchange,提问作者Henrik Truelsen
相关产品推荐
相关产品推荐

