err = sock.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)
if err == 0:
    print('connected')

非阻塞 connect 后立即返回 -1,errno 是 115 EINPROGRESS,代码按失败处理,5 分钟内重连了 900 次,对端 SYN 队列被打满。先别急着动参数,把报错原文和时间点记下来,顺序反了容易白折腾。

原因不复杂,非阻塞 connect 发起后内核还在等 SYN-ACK,返回 EINPROGRESS 表示正在进行而不是失败。真正的结果要等 socket 可写之后用 SO_ERROR 去取。

「EINPROGRESS 连接」改完先别急着全量,挑一台机器放半天,真有问题这段时间就能看出来。动手前把原文件复制一份带时间戳,出问题立刻换回去,比现场分析快得多。

一次只改一处,改完立刻验证,几个改动叠在一起,出问题就说不清是谁导致的。先做最小复现,能稳定跑出来的问题,排查成本会低一个数量级。

别只看报错的最后一行,往上看几行,真正的起因通常在上面。

处理上按这个顺序:errno 为 EINPROGRESS 时继续等待而不是重连;用 select 等 socket 可写;可写后读 SO_ERROR 判断结果;值为 0 才算连接建立成功。

改完只确认一件事:改完后重连次数从 900 降到 3,建连成功率 100%,SYN 队列不再溢出。

作者 9823189