Python SimpleHTTPRequestHandler服务器退出后留下套接字在TIME_WAIT状态。

5

我编写了一个简单的服务器,继承了 SimpleHTTPRequestHandler

如果我在没有向服务器发送任何请求的情况下启动和停止它,则可以在同一端口上重新启动而无需处理问题。

启动后,netstat 看起来像这样:

sam@hersheezy:server$ sudo netstat -na --program | grep 8001
tcp        0      0 0.0.0.0:8001            0.0.0.0:*               LISTEN      23392/python

发出请求后,即使请求已完成,netstat 也会显示如下结果:

sam@hersheezy:server$ sudo netstat -na --program | grep 8001
tcp        0      0 0.0.0.0:8001            0.0.0.0:*               LISTEN      23392/python    
tcp        0      0 127.0.0.1:8001          127.0.0.1:48659         TIME_WAIT   -

然后,我使用 C-c 来杀死服务器,此时 netstat 的输出如下(此时我无法重新启动服务器,因为端口已被占用):

sudo netstat -na --program | grep 8001
tcp        0      0 127.0.0.1:8001          127.0.0.1:48674         TIME_WAIT   - 

很明显我没有正确关闭某些内容。发送回复的代码如下:

"""
reply is an object that can be json encoded that is written with a response code 200
"""
def send_provider_reply(self, replyobj):
    try:
        str_reply = json.dumps(replyobj)
        self.send_response(200)
        self.send_header('Content-type', 'application/json')
        self.end_headers()
        #do we need to send a newline??
        self.wfile.write(str_reply)
    except:
        traceback.print_exc()
        self.send_err(500, 'failed after provider creation')
1个回答

6

SO_LINGER套接字选项确实可以防止套接字进入TIME_WAIT状态。但是TIME_WAIT的存在是有原因的:它应该保护您免受旧连接的滞留数据包的影响。因此,TIME_WAIT的默认持续时间是两倍的网络往返时间。因此,在TIME_WAIT中找到一些旧连接是正常的。

为了给出一些背景信息:在服务器端,使用监听套接字时,有SO_REUSEADDR套接字选项。它允许监听套接字在TIME_WAIT结束之前成功绑定。对于始终应该侦听相同端口(例如:端口80、443的Web服务器)的服务器进程而言,这是必须的。

典型的Python服务器代码可能包含如下内容:

...
listener = socket(AF_INET, SOCK_STREAM)
listener.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
listener.bind((HOST, PORT))
listener.listen(32)
...

我认为我理解了保护免受滞留数据包的部分,但我不太明白为什么这是一件好事:“它允许侦听套接字在TIME_WAIT结束之前成功绑定”。我知道其他可以快速停止/启动的服务器(如nginx),他们如何避免这种情况发生?谢谢! - Hersheezy
1
对于使用SocketServer.TCPServer及其SimpleHTTPRequestHandler的人(我假设:每个人),设置SO_REUSEADDR的简单方法是在初始化TCPServer之前执行以下操作:SocketServer.TCPServer.allow_reuse_address = True - Guss

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接