我正在尝试解决网络连接问题,试图了解为什么有些用户可以在开机时看到一个盒子,而其他用户可能需要近 20 秒才能看到它。它在我们的本地程序中造成了一些致命的问题。
为此,我运行了一个简单的最小可验证 python 脚本来尝试找出发生了什么:
import socket
import time
import errno
HOST = '192.168.1.1'
PORT = 12345
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(1)
while(True):
err = s.connect_ex((HOST, PORT))
if err == 0:
print("CONNECTED")
else:
print("NO CONNECTION: {0}".format(errno.errorcode[err]))
time.sleep(2)
当我运行此代码时,我看到一个一致的模式:EAGAIN,后跟 10 个 EALREADY 实例。当它确实连接时,“CONNECTED”将替换周期的 EAGAIN 位。
我认为将超时设置为 1 秒,然后等待 2 秒,应该可以让我更快地中止后台的连接调用,但它似乎没有任何效果。是否有我可以设置的 TCP 选项,或者我可以调整的 Windows 设置,以确保在轮询远程设备连接情况时不会出现这些尴尬的 20 秒阻塞?
最佳答案
通过在套接字上设置超时,socket.connect_ex()
成为非阻塞操作。这就是为什么在循环中重复调用 connect_ex()
时会出现 EAGAIN
和 EALREADY
错误 - EAGAIN
on第一个调用指示连接无法立即完成,并且正在后台进行中,然后后续调用中的 EALREADY
指示现有连接仍在进行中且尚未完成。
您的循环只是运行,直到连接最终以成功或失败结束,无论需要多长时间。您设置的套接字超时不符合该逻辑。
要执行您要求的操作,请与连接循环并行运行您自己的计时器,然后如果在 socket.connect_ex()
返回最终结果之前计时器已过,则关闭套接字。
或者,完全摆脱循环。
调用一次socket.connect_ex()
,如果返回EAGAIN
,则使用select.select()
等待连接完成。它有一个超时
参数。如果挂起的连接尝试成功连接到服务器,TCP 套接字将进入可写状态。如果 select()
超时或报告错误,请关闭套接字。
或者,尝试使用 socket.create_connection()
,它也有一个 timeout
参数。
关于windows - 有没有办法缩短 connect_ex() 的超时时间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56760686/