服務端開發的同學,可能經常發現,bind的時候會提示"bind failed: address already in use",本文我們就對這個問題分析一下。
當連線的一方主動關閉連線,在接收到對端的 fin 報文之後,主動關閉連線的一方會在 time_wait 這個狀態裡停留一段時間,這個時間大約為 2msl。當通過伺服器端發起的關閉連線操作,引起了乙個已有的 tcp 連線處於 tme_wait 狀態,正是這個 time_wait 的連線,使得伺服器重啟時,繼續繫結在同樣的位址與埠時出現了"bind failed: address already in use"報錯。
乙個 tcp 連線是通過四元組(源位址、源埠、目的位址、目的埠)來唯一確定的,如果每次客戶端使用的本地埠都不同,就不會和已有的四元組衝突,也就不會有 time_wait 的新舊連線衝突的問題。
即使小概率的出現新舊連線衝突的問題,正如在我的博文《tcp四次揮手調優》的文章指出的,開啟tcp_timestamps選項,那麼linux可以通過時間戳分析從新舊連線的資料。
故tcp提供了如下選項開啟
int on = 1;
setsockopt(listenfd, sol_socket, so_reuseaddr, &on, sizeof(on));
so_reuseaddr 選項用來告訴作業系統核心,如果埠已被占用,但是 tcp 連線狀態位於 time_wait ,可以重用埠。如果埠忙,而 tcp 處於其他狀態,重用埠時依舊得到「address already in use」的錯誤資訊。
so_reuseaddr其實還有如下的作用:
so_reuseaddr 套接字選項還有乙個作用,那就是本機伺服器如果有多個位址,可以在不同位址上使用相同的埠提供服務。比如,一台伺服器有 192.168.1.100 和 10.10.2.100 等多個位址,我們可以在這台機器上啟動三個不同的 http 服務,第乙個以 192.168.1.100 和埠 80 啟動;第二個以 10.10.2.100 和埠 80 啟動;第三個以本地通配位址 any 和埠 80 啟動。這樣目的位址為192.168.1.100 ,目的埠為 80 的連線請求會被發往第乙個服務;目的位址為 10.10.2.100 ,目的埠為 80 的連線請求會被發往第二個服務。我們必須給這三個服務設定 so_reuseaddr 套接字選項,否則第二個和第三個服務呼叫 bind 繫結到 80 埠時會出錯。
今天我們分析了「address already in use」產生的原因和解決方法。你只要記住一句話,在所有 tcp 伺服器程式中,呼叫 bind 之前請設定 so_reuseaddr 套接字選項。這不會產生危害,相反,它會幫助我們在很快時間內重啟服務端程式,而這一點恰恰是很多場景所需要的。
解決埠占用問題
有時候我們在啟動應用程式時常出現埠占用的問題,那麼如何查出占用該埠的應用程式呢?1.在cmd下輸入netstat ano,這時會列出所有埠的情況 若此時的應用程式太多,可能你會看不到上面列出的一系列值,你需要在右鍵該視窗,在該視窗中的布局中把螢幕緩衝區的大小調大一點 2.在本地位址中冒號的後面找到你...
80埠占用問題
我們在安裝使用phpstudy的過程中經常會遇到80埠被占用的情況,導致phpstudy的apache服務無法啟動 apache後邊顯示紅色方框,綠色圓點表示啟動 第一步 我們可以通過 其他選單選項 埠常規設定 httpd埠 的值改為8080或者90等埠。改好後重啟phpstudy,正常情況下這就可...
windows埠占用問題
前言 埠占用問題幾乎每個開發人員都會遇到,每次用每次查,下面來記錄下解決過程,以便日後需要。正文1 調出命令視窗 windows r 組合鍵,調出命令視窗 2 查詢占用埠對應的pid 程序號 列出所有埠占用情況 netstat ano 精確找到被占用的埠對應的pid netstat ano find...