带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
相关产品推荐
相关产品推荐

