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

带if循环的Socket运行异常:关闭失败及重连需求咨询

问题解答

1. Socket无法关闭的原因及解决方法

首先,你遇到的Errno 10022错误直接原因是**shutdown()的参数不合法**。Python的socket.shutdown()函数只接受三个有效值:

  • socket.SHUT_RD(对应数值0):关闭socket的接收通道,不再接收数据
  • socket.SHUT_WR(对应数值1):关闭socket的发送通道,不再发送数据
  • socket.SHUT_RDWR(对应数值2):同时关闭接收和发送通道

你传入的10是完全无效的参数,系统自然会返回"无效参数"的错误。

除此之外,你的代码还有一个逻辑问题:就算你正确关闭了socket,外层的while True循环还会继续执行,下次进入if分支时,你会尝试用已经关闭的socket去接收数据,这会触发新的异常。

解决步骤:

  • 替换shutdown()的参数为合法值,推荐用socket.SHUT_RDWR来彻底关闭双向通信,再调用close()
  • 关闭socket后,将socket对象置为None,或者设置一个标志位,避免后续循环复用已关闭的socket
  • 加入异常处理,避免socket操作的意外错误导致程序崩溃

修正后的else分支示例:

else:
    print('Unchecked going to close socket')
    if s is not None:
        try:
            s.shutdown(socket.SHUT_RDWR)
        except Exception as e:
            print(f"Shutdown warning: {e}")  # 处理socket已断开的情况
        s.close()
        s = None  # 标记为None,方便下次重新创建连接

2. 关闭Socket后能否不重启程序,再次勾选重新建立连接?

完全可以!但需要调整你的代码结构——当前你把socket的创建和连接放在了while循环外面,一旦关闭就无法复用。我们可以把socket的初始化逻辑移到if分支内部,每次勾选时检查socket状态,按需重新创建连接。

调整后的完整代码示例:

def show_markers(self):
    s = None  # 初始化socket为None
    host = socket.gethostbyname('192.168.225.12')
    scale = 0
    while True:
        if self.iconAction.isChecked():
            # 检查socket是否未创建或已关闭,需要重新连接
            if s is None or s._closed:
                print('Reconnecting to server...')
                s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                s.connect((host, port))
            
            print('Checked')
            m = QgsVertexMarker(self.iface.mapCanvas())
            
            # 注意:连续recv两次可能存在粘包风险,建议后续优化数据解析逻辑
            data = s.recv(SIZE)
            data1 = s.recv(SIZE)
            
            # 处理远程端主动断开连接的情况
            if not data or not data1:
                print("Connection closed by remote server")
                s.close()
                s = None
                continue
            
            c = data.decode()
            d = data1.decode()
            x = float(c)
            y = float(d)
            
            print("printing X :", x)
            print("printing Y :", y)
            
            rect = QgsRectangle(float(x)-scale, float(y)-scale, float(x)+scale, float(y)+scale)
            me = self.iface.mapCanvas()
            me.setExtent(rect)
            me.refresh()
            
            m.setCenter(QgsPointXY(x, y))
            m.setColor(QColor(255, 0, 0))
            m.setIconSize(7)
            m.setIconType(QgsVertexMarker.ICON_X)
            m.setPenWidth(3)
        else:
            # 仅当socket存在且未关闭时,执行关闭操作
            if s is not None and not s._closed:
                print('Unchecked going to close socket')
                try:
                    s.shutdown(socket.SHUT_RDWR)
                except Exception as e:
                    print(f"Shutdown warning: {e}")
                s.close()
                s = None
        
        # 加入短暂延时,避免无限循环占用过高CPU
        import time
        time.sleep(0.1)

额外注意事项:

  • 连续调用s.recv(SIZE)容易出现粘包问题,建议在发送端和接收端约定统一的数据格式(比如用换行符分隔,或者固定长度的头部标识数据长度),确保能正确解析出x和y的值
  • 无限循环会消耗大量CPU资源,加入time.sleep(0.1)可以有效降低资源占用
  • 建议给socket操作加上完整的异常捕获(比如ConnectionRefusedError、ConnectionResetError等),避免程序意外崩溃

内容的提问来源于stack exchange,提问作者Rahul Verma

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:25:49