2012-03-05 69 views
4

後,我寫了一個簡單的服務器,它擴展了SimpleHTTPRequestHandler蟒蛇SimpleHTTPRequestHandler服務器離開插座TIME_WAIT狀態退出

如果我啓動和停止它,而無需對服務器進行任何請求,我可以在同一個端口上啓動備份沒有問題。

啓動時,一個netstat的看起來是這樣的:一個請求時

 
[email protected]:server$ sudo netstat -na --program | grep 8001 
tcp  0  0 0.0.0.0:8001   0.0.0.0:*    LISTEN  23392/python 

後,netstat的看起來像這樣(請求完成後也):

 
[email protected]: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 - 

然後,我殺使用Cc和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') 

回答

5

套接字選項SO_LINGER確實會阻止套接字進入TIME_WAIT。但是TIME_WAIT的存在是有原因的:它應該保護你免受舊連接的延遲包裹。因此,TIME_WAIT的默認持續時間是網絡往返的兩倍。因此,在TIME_WAIT中找到一些較舊的連接是正常的。

給一些上下文:在服務器端,使用偵聽套接字,有SO_REUSEADDR套接字選項。它允許偵聽套接字在TIME_WAIT結束之前成功綁定。對於服務器進程,它總是應該監聽同一個端口(想想:在端口80,443處的webserver),這是必須的。對於服務器

典型的Python代碼可能包含這樣的事情:

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

我想我跟着你從揮之不去的分組部的保護,但我不明白爲什麼這是一件好事:「它允許偵聽套接字在TIME_WAIT結束之前成功綁定「。我知道可以快速停止/啓動的其他服務器(例如nginx),他們做了什麼來避免這種情況?謝謝! – Hersheezy 2012-03-06 03:22:25

+0

他們使用SO_REUSEADDR。 – 2012-03-06 07:30:33