【问题标题】:Is there a way to shorten connect_ex()'s timeout?有没有办法缩短 connect_ex() 的超时时间?
【发布时间】:2019-11-07 16:25:06
【问题描述】:

我正在尝试解决网络中的连接问题,试图了解为什么有些用户可以在开机时立即看到一个框,而其他用户可能需要将近 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 秒阻塞?

【问题讨论】:

    标签: windows python-2.7 sockets


    【解决方案1】:

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

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

    要执行您的要求,请将您自己的计时器与连接循环并行运行,然后如果计时器在socket.connect_ex() 返回其最终结果之前结束,则关闭套接字。

    或者,完全摆脱循环。

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

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

    【讨论】:

    • 哦。所以超时是在阻塞上,而不是连接操作本身的超时。这样就可以解释了,谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-18
    • 1970-01-01
    • 2022-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多