TCP端口占用:服務(wù)端程序退出后,端口為何依然被占用且如何解決?

TCP端口占用:服務(wù)端程序退出后,端口為何依然被占用且如何解決?

python TCP服務(wù)端端口占用難題:程序退出后端口仍被占用及解決方案

在使用Python開發(fā)TCP服務(wù)器時,一個常見問題是:服務(wù)器程序關(guān)閉后,目標端口仍然處于占用狀態(tài),導致無法立即重啟服務(wù)器。本文將深入探討這個問題并提供有效的解決方法

問題:開發(fā)者使用socket.socket()創(chuàng)建TCP服務(wù)器,并結(jié)合multiprocessing.pool進行多進程處理客戶端請求。服務(wù)器意外終止后,lsof -i :6001未顯示端口6001被占用,但重啟時卻出現(xiàn)OSError: [errno 98] Address already in use錯誤。然而,netstat -anp | grep 6001顯示大量處于TIME_WaiT狀態(tài)的連接。

原因:這是TCP連接的TIME_WAIT狀態(tài)導致的。服務(wù)器異常退出時,部分TCP連接可能未正確關(guān)閉,進入TIME_WAIT狀態(tài)。操作系統(tǒng)會保留這些端口一段時間(數(shù)分鐘到數(shù)十分鐘),以確保數(shù)據(jù)傳輸可靠性。lsof關(guān)注進程與文件的關(guān)聯(lián),而TIME_WAIT連接并非由任何進程直接持有,所以lsof無法檢測到;netstat則能顯示網(wǎng)絡(luò)連接狀態(tài),因此能看到TIME_WAIT連接。

解決方案:在服務(wù)器程序綁定端口前,設(shè)置SO_REUSEADDR選項。此選項允許在端口處于TIME_WAIT狀態(tài)時立即綁定該端口。修改后的代碼如下:

serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  # 在bind之前添加 serversocket.bind(('0.0.0.0', port)) # ... 其他代碼 ...

添加serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)即可解決TIME_WAIT狀態(tài)導致的端口占用問題。 linux 3.9及以后的內(nèi)核增加了SO_REUSEPORT選項,它比SO_REUSEADDR更精細,建議同時設(shè)置這兩個選項。windows系統(tǒng)可能還需要額外設(shè)置SO_EXCLUSIVEADDRUSE選項。

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點贊12 分享