Python socket.connect()报OSError[Errno22]无效参数问题排查
问题:遍历ARP列表设备连接指定端口时出现Errno22无效参数错误
我写了一段Python代码,想遍历ARP列表里的设备IP,尝试用socket连接指定端口,代码如下:
import socket import os my_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) devices = [] print("Looking for open server. . .") for device in os.popen('arp -a'): devices.append(device.split()[1].strip("()")) # .strip("()") # print(devices) make_server = True host = "192.168.4.24" # "127.0.1.1" port = 8000 for device in devices: try: my_socket.connect((device, port)) make_server = False print(f"Connected to {device}") break except socket.error as error: pass # print(error) if make_server: my_socket.connect((socket.gethostbyname(socket.gethostname()), port)) print(f"Connected to {socket.gethostbyname(socket.gethostname())}")
执行后抛出错误:
Traceback (most recent call last): File "/Users/user/PycharmProjects/LAN_chat_app/Testing 1.py", line 41, in <module> my_socket.connect((socket.gethostbyname(socket.gethostname()), port)) OSError: [Errno 22] Invalid argument
测试发现:循环中第一次连接会抛出ConnectionRefusedError[Errno61](连接被拒绝),能正常捕获;但从第二次迭代开始,调用my_socket.connect((device, port))直接返回OSError[Errno22]无效参数错误,没法继续遍历其他设备,最后连本地主机也报同样的错。
环境:PyCharm 2021.1(社区版),macOS 12.5
原因分析
TCP套接字对象在调用connect()失败后,会进入不可复用的错误状态,不能再用来发起新的连接请求。你只在代码开头创建了一次套接字,第一次连接失败后,这个套接字已经处于错误状态,后续再调用connect()就会直接返回无效参数的错误。
解决方案
每次尝试连接前都创建一个新的套接字对象,或者在每次连接失败后关闭当前套接字并重新创建。
修改后的代码示例:
import socket import os devices = [] print("Looking for open server. . .") for device in os.popen('arp -a'): devices.append(device.split()[1].strip("()")) # .strip("()") # print(devices) make_server = True port = 8000 for device in devices: # 每次循环新建套接字 my_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 设置超时,避免长时间等待 my_socket.settimeout(1) try: my_socket.connect((device, port)) make_server = False print(f"Connected to {device}") break except socket.error as error: # 关闭失败的套接字 my_socket.close() pass # print(error) if make_server: # 新建套接字连接本地 local_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) local_ip = socket.gethostbyname(socket.gethostname()) try: local_socket.connect((local_ip, port)) print(f"Connected to {local_ip}") except socket.error as e: print(f"Failed to connect to local: {e}") finally: local_socket.close()
内容的提问来源于stack exchange,提问作者Bug In A Rug
相关产品推荐
相关产品推荐

