socket.SO_REUSEADDR

最后更新时间: 2018-04-15 | 作者: AberSheeran | 捐助

最近在手写分布式爬虫的时候遇到一个问题,就是负责任务分发的服务器在关掉试图重启的时候总显示端口被占用,但又查不到端口被占用的进程号。

1
[ERROR] Address already in use

一番谷歌之后得知,操作系统的网络栈会非常谨慎的处理连接的关闭,仅仅用于监听的服务器套接字是可以立即关闭并操作系统忽略的,但是对于实际与客户端进行通信的连接套接字就不行了。即使客户端和服务器都关闭了连接并向对方发从了FIN数据包,连接套接字也无法立即取消。为什么呢?因为即使网络栈发送了最后一个数据包将套接字关闭,也还是无法确认该数据包是否可以被接收。如果数据包正好被网络丢弃了,那么另一方无法得知该数据包长时间无法传达的原因,可能会重新发送FIN数据包,希望能收到响应。

操作系统对上述问题的解决方案为,一个应用程序任务某个TCP连接最终关闭了,操作系统的网络栈实际上会在一个等待状态中将该连接的记录保存最多4分钟。RFC将这些状态命名为CLOSE-WAIT 和TIME-WAIT,当关闭的套接字还处于其中某一状态时,任何最终的FIN数据包都是可以得到适当响应的。

如何解决

只需要在server.bind()之前增加一行代码:

1
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

谷歌结果说它还有另外的三个作用:

标签: PythonSocket
收录于#杂记