You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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()

问题分析

  1. 全局变量命名冲突:导入的socket模块被同名全局变量覆盖。第一次调用connect()时,socket = socket.socket()将全局的socket从模块对象替换为socket实例;第二次调用connect()时,socket.socket()变成调用实例的socket属性,而socket对象无此属性,直接报错。
  2. 客户端逻辑错误: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 14:55:18