s.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
              struct.pack('ii', 1, 5))
s.shutdown(socket.SHUT_WR)

服务端发完响应立刻 close,客户端读到的数据只有前半段,随后抛 ConnectionResetError 104,抓包看到的是 RST 而不是 FIN。这类现象通常不是突然出现的,往前翻半天日志能看到苗头。

追下去是这么回事:SO_LINGER 的 l_onoff 非 0 且 l_linger 为 0 时,close 会直接发 RST,缓冲区里没发完的数据全部丢弃。客户端还没来得及读,连接就被重置。

这次卡住的地方就在「SO_LINGER RST」这一环,单独把它拎出来验证,别和其他改动混在同一次发布里。同一份配置存在多处的,先确认改的是被加载的那一份。

新版本先放一台机器上跑一天再全量,问题一般在这段时间暴露。备份不是备了就行,恢复一次才算数,很多备份文件打开才发现是空的。

接口问题先分清是没发出去、发出去了没收到,还是收到了处理失败。

处理上按这个顺序:把 l_onoff 置 0 走正常四次挥手;确需限时就设一个合理的 linger 秒数;close 前先 shutdown(SHUT_WR);等对端关闭后再释放。

确认没问题再收工,改完后抓包里能看到正常的 FIN 四次挥手,客户端接收完整率 100%,Errno 104 不再出现。

作者 9823189