TCP socket綁定(bind)失敗---Address already is use原因

原文鏈接:https://blog.csdn.net/fern_girl/article/details/73657825
版權聲明:本文爲博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
原文鏈接:https://blog.csdn.net/fern_girl/article/details/73657825

我們前面介紹了三種tcp_server編寫多進程多線程服務器編寫,在測試這三個servet我們遇到一個問題,就是當我們綁定一個端口號後,ctrl-z結束掉server服務器,此時再次綁定該端口號會出現這樣的出錯提示:

這裏寫圖片描述

顯示端口號正在被使用,可是我們已經關閉了服務器了,爲什麼不能使用呢?但過一端時間之後,該端口號又可以使用了,這又是爲什麼呢?

IBM官網給出了具體解釋linux套接字編程的五大隱患
其中,對於上述問題的描述是:

隱患 3.地址使用錯誤(EADDRINUSE)
您可以使用 bind API 函數來綁定一個地址(一個接口和一個端口)到一個套接字端點。可以在服務器設置中使用這個函數,以便限制可能有連接到來的接口。也可以在客戶端設置中使用這個函數,以便限制應當供出去的連接所使用的接口。bind 最常見的用法是關聯端口號和服務器,並使用通配符地址(INADDR_ANY),它允許任何接口爲到來的連接所使用。
bind 普遍遭遇的問題是試圖綁定一個已經在使用的端口。該陷阱是也許沒有活動的套接字存在,但仍然禁止綁定端口(bind 返回 EADDRINUSE),它由 TCP 套接字狀態 TIME_WAIT 引起。該狀態在套接字關閉後約保留 2 到 4 分鐘。在 TIME_WAIT 狀態退出之後,套接字被刪除,該地址才能被重新綁定而不出問題。
等待 TIME_WAIT 結束可能是令人惱火的一件事,特別是如果您正在開發一個套接字服務器,就需要停止服務器來做一些改動,然後重啓。幸運的是,有方法可以避開 TIME_WAIT 狀態。可以給套接字應用 SO_REUSEADDR 套接字選項,以便端口可以馬上重用
考慮清單 3 的例子。在綁定地址之前,我以 SO_REUSEADDR 選項調用 setsockopt。爲了允許地址重用,我設置整型參數(on)爲 1 (不然,可以設爲 0 來禁止地址重用)。

我的理解:TCP的斷開連接是一個四次揮手的過程,假設客戶端先斷開連接,此時服務器端向客戶端發送斷開請求時,客戶端處於TIME_WAIT,這個時間是2MSL,確保服務器端能夠收到確認消息,正常退出,也就是說,在這個時間過程中,服務器是沒有斷開連接的,那麼端口號就一直被佔用,知道2MSL時間過後。服務器斷開連接,釋放資源。

修改方法:
這裏寫圖片描述

在socket和bind之間加上sesockopt函數。

這裏寫圖片描述
再次請求相同的地址和端口號時,需要ctrl-c斷開之前調用的服務器,否則,它將一直處於 listen狀態

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章