python -- socket关闭后地址占用问题

class MyHttpHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        print "do get"
        self.send_response(code=200)
        self.end_headers()
        self.wfile.write("hello world")

if __name__ == '__main__':
    serv = TCPServer(('', 20001), MyHttpHandler)
    serv.serve_forever()

上面这段代码,运行,client访问多次后关闭,再启动,会报一个socket.error: [Errno 48] Address already in use的错。lsof -i:20001 没能找到任何进程占用端口,一个乍一看很迷的错误,记录下,怕以后忘掉。

解决方案很简单,增加TCPServer.allow_reuse_address = True。具体起作用的为socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)这。

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

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

因此,当服务器试图声明某个几分钟前运行的连接所使用的端口时,实际上是在试图声明从某种意义上仍在使用的端口。所以就报错了~

而SO_REUSEADDR可以指明应用程序能够使用一些网络客户端之前的连接正在关闭的端口。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1、TCP状态linux查看tcp的状态命令:1)、netstat -nat 查看TCP各个状态的数量2)、lso...
    北辰青阅读 13,181评论 0 11
  • 一: 网络各个协议:TCP/IP、SOCKET、HTTP 网络七层由下往上分别为物理层、数据链路层、网络层、传输层...
    iYeso阅读 5,276评论 0 13
  • 一、网络各个协议:TCP/IP、SOCKET、HTTP等 网络七层由下往上分别为物理层、数据链路层、网络层、传输层...
    杯水救车薪阅读 6,752评论 0 17
  • 感知型摄像机也叫Intelligent IPC,是2014年推出的一种新型智能摄像机,不同于传统的智能摄像机,它由...
    Kedacom1995阅读 4,457评论 0 1
  • 听歌的青年 听歌的青年, 手指打着节拍, 律动,舞蹈,梦马。 微风过处弹钢琴, 抚天长,姑娘的俏脸, 张手作翅, ...
    南溪向南北歌流海阅读 1,287评论 0 0