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

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

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

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

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

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

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

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)導(dǎo)致的端口占用問題。 linux 3.9及以后的內(nèi)核增加了SO_REUSEPORT選項(xiàng),它比SO_REUSEADDR更精細(xì),建議同時(shí)設(shè)置這兩個(gè)選項(xiàng)。windows系統(tǒng)可能還需要額外設(shè)置SO_EXCLUSIVEADDRUSE選項(xiàng)。

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