有没有办法缩短connect_ex()的超时时间?

时间:2019-06-25 19:16:48

标签: windows python-2.7 sockets

我正在尝试解决网络中的连接问题,试图了解为什么某些用户在开机时可以看到一个盒子,而其他用户可能需要近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秒,应该可以让我更快地在后台中止connect调用,但这似乎没有任何作用。有没有我可以设置的TCP选项或我可以调整的Windows设置,以确保在轮询远程设备以进行连接时不会出现这些尴尬的20秒块?

1 个答案:

答案 0 :(得分:1)

通过在套接字上设置超时,socket.connect_ex()成为非阻塞操作。这就是为什么在循环中反复调用EAGAIN时遇到EALREADYconnect_ex()错误的原因-第一次调用EAGAIN表示连接无法立即完成并且正在进行中在后台,然后在后续调用中EALREADY表示现有连接仍在进行中,尚未完成。

您的循环会一直运行,直到连接最终以成功或失败结束,无论需要多长时间。您设置的套接字超时不会影响该逻辑。

要执行所需的操作,请在连接循环的同时运行自己的计时器,然后在socket.connect_ex()返回其最终结果之前,如果计时器已过,则关闭套接字。

或者,完全摆脱循环。

呼叫socket.connect_ex()一次,如果返回EAGAIN,则使用select.select()等待连接完成。它具有一个timeout参数。如果挂起的连接尝试成功连接到服务器,则TCP套接字将进入可写状态。如果select()超时或报告错误,请关闭套接字。

或者尝试使用socket.create_connection(),它也有一个timeout参数。