大家好,我是小林。

之前有讀者在字節(jié)面試的時(shí)候,被問到:TCP 和 UDP 可以同時(shí)監(jiān)聽相同的端口嗎?

關(guān)于端口的知識(shí)點(diǎn),還是挺多可以講的,比如還可以牽扯到這幾個(gè)問題:


(資料圖)

多個(gè) TCP 服務(wù)進(jìn)程可以同時(shí)綁定同一個(gè)端口嗎?客戶端的端口可以重復(fù)使用嗎?客戶端 TCP 連接 TIME_WAIT 狀態(tài)過多,會(huì)導(dǎo)致端口資源耗盡而無(wú)法建立新的連接嗎?

所以,這次就跟大家盤一盤這些問題。

TCP 和 UDP 可以同時(shí)綁定相同的端口嗎?

其實(shí)我感覺這個(gè)問題「TCP 和 UDP 可以同時(shí)監(jiān)聽相同的端口嗎?」表述有問題,這個(gè)問題應(yīng)該表述成「TCP 和 UDP 可以同時(shí)綁定相同的端口嗎?」

因?yàn)椤副O(jiān)聽」這個(gè)動(dòng)作是在 TCP 服務(wù)端網(wǎng)絡(luò)編程中才具有的,而 UDP 服務(wù)端網(wǎng)絡(luò)編程中是沒有「監(jiān)聽」這個(gè)動(dòng)作的。

TCP 和 UDP 服務(wù)端網(wǎng)絡(luò)相似的一個(gè)地方,就是會(huì)調(diào)用 bind 綁定端口。

給大家貼一下 TCP 和 UDP 網(wǎng)絡(luò)編程的區(qū)別就知道了。

TCP 網(wǎng)絡(luò)編程如下,服務(wù)端執(zhí)行 listen() 系統(tǒng)調(diào)用就是監(jiān)聽端口的動(dòng)作。

TCP 網(wǎng)絡(luò)編程

UDP 網(wǎng)絡(luò)編程如下,服務(wù)端是沒有監(jiān)聽這個(gè)動(dòng)作的,只有執(zhí)行 bind() 系統(tǒng)調(diào)用來(lái)綁定端口的動(dòng)作。

UDP 網(wǎng)絡(luò)編程

TCP 和 UDP 可以同時(shí)綁定相同的端口嗎?

答案:可以的。

在數(shù)據(jù)鏈路層中,通過 MAC 地址來(lái)尋找局域網(wǎng)中的主機(jī)。在網(wǎng)際層中,通過 IP 地址來(lái)尋找網(wǎng)絡(luò)中互連的主機(jī)或路由器。在傳輸層中,需要通過端口進(jìn)行尋址,來(lái)識(shí)別同一計(jì)算機(jī)中同時(shí)通信的不同應(yīng)用程序。

所以,傳輸層的「端口號(hào)」的作用,是為了區(qū)分同一個(gè)主機(jī)上不同應(yīng)用程序的數(shù)據(jù)包。

傳輸層有兩個(gè)傳輸協(xié)議分別是 TCP 和 UDP,在內(nèi)核中是兩個(gè)完全獨(dú)立的軟件模塊。

當(dāng)主機(jī)收到數(shù)據(jù)包后,可以在 IP 包頭的「協(xié)議號(hào)」字段知道該數(shù)據(jù)包是 TCP/UDP,所以可以根據(jù)這個(gè)信息確定送給哪個(gè)模塊(TCP/UDP)處理,送給 TCP/UDP 模塊的報(bào)文根據(jù)「端口號(hào)」確定送給哪個(gè)應(yīng)用程序處理。

因此, TCP/UDP 各自的端口號(hào)也相互獨(dú)立,如 TCP 有一個(gè) 80 號(hào)端口,UDP 也可以有一個(gè) 80 號(hào)端口,二者并不沖突。

驗(yàn)證結(jié)果

我簡(jiǎn)單寫了 TCP 和 UDP 服務(wù)端的程序,它們都綁定同一個(gè)端口號(hào) 8888。

運(yùn)行這兩個(gè)程序后,通過 netstat 命令可以看到,TCP 和 UDP 是可以同時(shí)綁定同一個(gè)端口號(hào)的。

多個(gè) TCP 服務(wù)進(jìn)程可以綁定同一個(gè)端口嗎?

還是以前面的 TCP 服務(wù)端程序作為例子,啟動(dòng)兩個(gè)同時(shí)綁定同一個(gè)端口的 TCP 服務(wù)進(jìn)程。

運(yùn)行第一個(gè) TCP 服務(wù)進(jìn)程之后,netstat 命令可以查看,8888 端口已經(jīng)被一個(gè) TCP 服務(wù)進(jìn)程綁定并監(jiān)聽了,如下圖:

接著,運(yùn)行第二個(gè) TCP 服務(wù)進(jìn)程的時(shí)候,就報(bào)錯(cuò)了“Address already in use”,如下圖:

我上面的測(cè)試案例是兩個(gè) TCP 服務(wù)進(jìn)程同時(shí)綁定地址和端口是:0.0.0.0 地址和8888端口,所以才出現(xiàn)的錯(cuò)誤。

如果兩個(gè) TCP 服務(wù)進(jìn)程綁定的 IP 地址不同,而端口相同的話,也是可以綁定成功的,如下圖:

所以,默認(rèn)情況下,針對(duì)「多個(gè) TCP 服務(wù)進(jìn)程可以綁定同一個(gè)端口嗎?」這個(gè)問題的答案是:如果兩個(gè) TCP 服務(wù)進(jìn)程同時(shí)綁定的 IP 地址和端口都相同,那么執(zhí)行 bind() 時(shí)候就會(huì)出錯(cuò),錯(cuò)誤是“Address already in use”。

注意,如果 TCP 服務(wù)進(jìn)程 A 綁定的地址是 0.0.0.0 和端口 8888,而如果 TCP 服務(wù)進(jìn)程 B 綁定的地址是 192.168.1.100 地址(或者其他地址)和端口 8888,那么執(zhí)行 bind() 時(shí)候也會(huì)出錯(cuò)。

這是因?yàn)?0.0.0.0 地址比較特殊,代表任意地址,意味著綁定了 0.0.0.0 地址,相當(dāng)于把主機(jī)上的所有 IP 地址都綁定了。

重啟 TCP 服務(wù)進(jìn)程時(shí),為什么會(huì)有“Address in use”的報(bào)錯(cuò)信息?

TCP 服務(wù)進(jìn)程需要綁定一個(gè) IP 地址和一個(gè)端口,然后就監(jiān)聽在這個(gè)地址和端口上,等待客戶端連接的到來(lái)。

然后在實(shí)踐中,我們可能會(huì)經(jīng)常碰到一個(gè)問題,當(dāng) TCP 服務(wù)進(jìn)程重啟之后,總是碰到“Address in use”的報(bào)錯(cuò)信息,TCP 服務(wù)進(jìn)程不能很快地重啟,而是要過一會(huì)才能重啟成功。

這是為什么呢?

當(dāng)我們重啟 TCP 服務(wù)進(jìn)程的時(shí)候,意味著通過服務(wù)器端發(fā)起了關(guān)閉連接操作,于是就會(huì)經(jīng)過四次揮手,而對(duì)于主動(dòng)關(guān)閉方,會(huì)在 TIME_WAIT 這個(gè)狀態(tài)里停留一段時(shí)間,這個(gè)時(shí)間大約為 2MSL。

當(dāng) TCP 服務(wù)進(jìn)程重啟時(shí),服務(wù)端會(huì)出現(xiàn) TIME_WAIT 狀態(tài)的連接,TIME_WAIT 狀態(tài)的連接使用的 IP+PORT 仍然被認(rèn)為是一個(gè)有效的 IP+PORT 組合,相同機(jī)器上不能夠在該 IP+PORT 組合上進(jìn)行綁定,那么執(zhí)行 bind() 函數(shù)的時(shí)候,就會(huì)返回了 Address already in use 的錯(cuò)誤。

而等 TIME_WAIT 狀態(tài)的連接結(jié)束后,重啟 TCP 服務(wù)進(jìn)程就能成功。

重啟 TCP 服務(wù)進(jìn)程時(shí),如何避免“Address in use”的報(bào)錯(cuò)信息?

我們可以在調(diào)用 bind 前,對(duì) socket 設(shè)置 SO_REUSEADDR 屬性,可以解決這個(gè)問題。

int on = 1;setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

因?yàn)镾O_REUSEADDR作用是:如果當(dāng)前啟動(dòng)進(jìn)程綁定的 IP+PORT 與處于TIME_WAIT 狀態(tài)的連接占用的 IP+PORT 存在沖突,但是新啟動(dòng)的進(jìn)程使用了 SO_REUSEADDR 選項(xiàng),那么該進(jìn)程就可以綁定成功。

舉個(gè)例子,服務(wù)端有個(gè)監(jiān)聽 0.0.0.0 地址和 8888 端口的 TCP 服務(wù)進(jìn)程。?

有個(gè)客戶端(IP地址:192.168.1.100)已經(jīng)和服務(wù)端(IP 地址:172.19.11.200)建立了 TCP 連接,那么在 TCP 服務(wù)進(jìn)程重啟時(shí),服務(wù)端會(huì)與客戶端經(jīng)歷四次揮手,服務(wù)端的 TCP 連接會(huì)短暫處于 TIME_WAIT 狀態(tài):

客戶端地址:端口 服務(wù)端地址:端口 TCP 連接狀態(tài)192.168.1.100:37272 172.19.11.200:8888 TIME_WAIT

如果 TCP 服務(wù)進(jìn)程沒有對(duì) socket 設(shè)置 SO_REUSEADDR 屬性,那么在重啟時(shí),由于存在一個(gè)和綁定 IP+PORT 一樣的TIME_WAIT 狀態(tài)的連接,那么在執(zhí)行 bind() 函數(shù)的時(shí)候,就會(huì)返回了 Address already in use 的錯(cuò)誤。

如果 TCP 服務(wù)進(jìn)程對(duì) socket 設(shè)置 SO_REUSEADDR 屬性了,那么在重啟時(shí),即使存在一個(gè)和綁定 IP+PORT一樣的TIME_WAIT 狀態(tài)的連接,依然可以正常綁定成功,因此可以正常重啟成功。

因此,在所有 TCP 服務(wù)器程序中,調(diào)用 bind 之前最好對(duì) socket 設(shè)置 SO_REUSEADDR 屬性,這不會(huì)產(chǎn)生危害,相反,它會(huì)幫助我們?cè)诤芸鞎r(shí)間內(nèi)重啟服務(wù)端程序。?

前面我提到過這個(gè)問題:如果 TCP 服務(wù)進(jìn)程 A 綁定的地址是 0.0.0.0 和端口 8888,而如果 TCP 服務(wù)進(jìn)程 B 綁定的地址是 192.168.1.100 地址(或者其他地址)和端口 8888,那么執(zhí)行 bind() 時(shí)候也會(huì)出錯(cuò)。

這個(gè)問題也可以由SO_REUSEADDR解決,因?yàn)樗牧硗庖粋€(gè)作用是:綁定的 IP地址 + 端口時(shí),只要 IP 地址不是正好(exactly)相同,那么允許綁定。?

比如,0.0.0.0:8888和192.168.1.100:8888,雖然邏輯意義上前者包含了后者,但是 0.0.0.0 泛指所有本地 IP,而 192.168.1.100 特指某一IP,兩者并不是完全相同,所以在對(duì) socket 設(shè)置SO_REUSEADDR 屬性后,那么執(zhí)行 bind() 時(shí)候就會(huì)綁定成功。

客戶端的端口可以重復(fù)使用嗎?

客戶端在執(zhí)行 connect 函數(shù)的時(shí)候,會(huì)在內(nèi)核里隨機(jī)選擇一個(gè)端口,然后向服務(wù)端發(fā)起 SYN 報(bào)文,然后與服務(wù)端進(jìn)行三次握手。

所以,客戶端的端口選擇的發(fā)生在 connect 函數(shù),內(nèi)核在選擇端口的時(shí)候,會(huì)從net.ipv4.ip_local_port_range這個(gè)內(nèi)核參數(shù)指定的范圍來(lái)選取一個(gè)端口作為客戶端端口。

該參數(shù)的默認(rèn)值是 32768 61000,意味著端口總可用的數(shù)量是 61000 - 32768 = 28232 個(gè)。

當(dāng)客戶端與服務(wù)端完成 TCP 連接建立后,我們可以通過 netstat 命令查看 TCP 連接。

$ netstat -napt協(xié)議 源ip地址:端口 目的ip地址:端口 狀態(tài)tcp 192.168.110.182.64992 117.147.199.51.443 ESTABLISHED

那問題來(lái)了,上面客戶端已經(jīng)用了 64992 端口,那么還可以繼續(xù)使用該端口發(fā)起連接嗎?

這個(gè)問題,很多同學(xué)都會(huì)說不可以繼續(xù)使用該端口了,如果按這個(gè)理解的話, 默認(rèn)情況下客戶端可以選擇的端口是 28232 個(gè),那么意味著客戶端只能最多建立 28232 個(gè) TCP 連接,如果真是這樣的話,那么這個(gè)客戶端并發(fā)連接也太少了吧,所以這是錯(cuò)誤理解。

正確的理解是,TCP 連接是由四元組(源IP地址,源端口,目的IP地址,目的端口)唯一確認(rèn)的,那么只要四元組中其中一個(gè)元素發(fā)生了變化,那么就表示不同的 TCP 連接的。所以如果客戶端已使用端口 64992 與服務(wù)端 A 建立了連接,那么客戶端要與服務(wù)端 B 建立連接,還是可以使用端口 64992 的,因?yàn)閮?nèi)核是通過四元祖信息來(lái)定位一個(gè) TCP 連接的,并不會(huì)因?yàn)榭蛻舳说亩丝谔?hào)相同,而導(dǎo)致連接沖突的問題。

比如下面這張圖,有 2 個(gè) TCP 連接,左邊是客戶端,右邊是服務(wù)端,客戶端使用了相同的端口 50004 與兩個(gè)服務(wù)端建立了 TCP 連接。

仔細(xì)看,上面這兩條 TCP 連接的四元組信息中的「目的 IP 地址」是不同的,一個(gè)是 180.101.49.12 ,另外一個(gè)是 180.101.49.11。

多個(gè)客戶端可以 bind 同一個(gè)端口嗎?

bind 函數(shù)雖然常用于服務(wù)端網(wǎng)絡(luò)編程中,但是它也是用于客戶端的。

前面我們知道,客戶端是在調(diào)用 connect 函數(shù)的時(shí)候,由內(nèi)核隨機(jī)選取一個(gè)端口作為連接的端口。

而如果我們想自己指定連接的端口,就可以用 bind 函數(shù)來(lái)實(shí)現(xiàn):客戶端先通過 bind 函數(shù)綁定一個(gè)端口,然后調(diào)用 connect 函數(shù)就會(huì)跳過端口選擇的過程了,轉(zhuǎn)而使用 bind 時(shí)確定的端口。

針對(duì)這個(gè)問題:多個(gè)客戶端可以 bind 同一個(gè)端口嗎?

要看多個(gè)客戶端綁定的IP+PORT 是否都相同,如果都是相同的,那么在執(zhí)行 bind() 時(shí)候就會(huì)出錯(cuò),錯(cuò)誤是“Address already in use”。

如果一個(gè)綁定在 192.168.1.100:6666,一個(gè)綁定在192.168.1.200:6666,因?yàn)?IP 不相同,所以執(zhí)行 bind() 的時(shí)候,能正常綁定。

所以, 如果多個(gè)客戶端同時(shí)綁定的 IP 地址和端口都是相同的,那么執(zhí)行 bind() 時(shí)候就會(huì)出錯(cuò),錯(cuò)誤是“Address already in use”。

一般而言,客戶端不建議使用 bind 函數(shù),應(yīng)該交由 connect 函數(shù)來(lái)選擇端口會(huì)比較好,因?yàn)榭蛻舳说亩丝谕ǔ6紱]什么意義。

客戶端 TCP 連接 TIME_WAIT 狀態(tài)過多,會(huì)導(dǎo)致端口資源耗盡而無(wú)法建立新的連接嗎?

針對(duì)這個(gè)問題要看,客戶端是否都是與同一個(gè)服務(wù)器(目標(biāo)地址和目標(biāo)端口一樣)建立連接。

如果客戶端都是與同一個(gè)服務(wù)器(目標(biāo)地址和目標(biāo)端口一樣)建立連接,那么如果客戶端 TIME_WAIT 狀態(tài)的連接過多,當(dāng)端口資源被耗盡,就無(wú)法與這個(gè)服務(wù)器再建立連接了。

但是,因?yàn)橹灰蛻舳诉B接的服務(wù)器不同,端口資源可以重復(fù)使用的。

所以,如果客戶端都是與不同的服務(wù)器建立連接,即使客戶端端口資源只有幾萬(wàn)個(gè), 客戶端發(fā)起百萬(wàn)級(jí)連接也是沒問題的(當(dāng)然這個(gè)過程還會(huì)受限于其他資源,比如文件描述符、內(nèi)存、CPU 等)。

如何解決客戶端 TCP 連接 TIME_WAIT 過多,導(dǎo)致無(wú)法與同一個(gè)服務(wù)器建立連接的問題?

前面我們提到,如果客戶端都是與同一個(gè)服務(wù)器(目標(biāo)地址和目標(biāo)端口一樣)建立連接,那么如果客戶端 TIME_WAIT 狀態(tài)的連接過多,當(dāng)端口資源被耗盡,就無(wú)法與這個(gè)服務(wù)器再建立連接了。

針對(duì)這個(gè)問題,也是有解決辦法的,那就是打開net.ipv4.tcp_tw_reuse這個(gè)內(nèi)核參數(shù)。

因?yàn)殚_啟了這個(gè)內(nèi)核參數(shù)后,客戶端調(diào)用 connect 函數(shù)時(shí),如果選擇到的端口,已經(jīng)被相同四元組的連接占用的時(shí)候,就會(huì)判斷該連接是否處于 TIME_WAIT 狀態(tài),如果該連接處于 TIME_WAIT 狀態(tài)并且 TIME_WAIT 狀態(tài)持續(xù)的時(shí)間超過了 1 秒,那么就會(huì)重用這個(gè)連接,然后就可以正常使用該端口了。

舉個(gè)例子,假設(shè)客戶端已經(jīng)與服務(wù)器建立了一個(gè) TCP 連接,并且這個(gè)狀態(tài)處于 TIME_WAIT 狀態(tài):

客戶端地址:端口 服務(wù)端地址:端口 TCP 連接狀態(tài)192.168.1.100:2222 172.19.11.21:8888 TIME_WAIT

然后客戶端又與該服務(wù)器(172.19.11.21:8888)發(fā)起了連接,在調(diào)用 connect 函數(shù)時(shí),內(nèi)核剛好選擇了 2222 端口,接著發(fā)現(xiàn)已經(jīng)被相同四元組的連接占用了:

如果沒有開啟net.ipv4.tcp_tw_reuse 內(nèi)核參數(shù),那么內(nèi)核就會(huì)選擇下一個(gè)端口,然后繼續(xù)判斷,直到找到一個(gè)沒有被相同四元組的連接使用的端口, 如果端口資源耗盡還是沒找到,那么 connect 函數(shù)就會(huì)返回錯(cuò)誤。如果開啟了 net.ipv4.tcp_tw_reuse 內(nèi)核參數(shù),就會(huì)判斷該四元組的連接狀態(tài)是否處于 TIME_WAIT 狀態(tài),如果連接處于 TIME_WAIT 狀態(tài)并且該狀態(tài)持續(xù)的時(shí)間超過了 1 秒,那么就會(huì)重用該連接,于是就可以使用 2222 端口了,這時(shí) connect 就會(huì)返回成功。

再次提醒一次,開啟了 net.ipv4.tcp_tw_reuse 內(nèi)核參數(shù),是客戶端(連接發(fā)起方) 在調(diào)用 connect() 函數(shù)時(shí)才起作用,所以在服務(wù)端開啟這個(gè)參數(shù)是沒有效果的。

客戶端端口選擇的流程總結(jié)

至此,我們已經(jīng)把客戶端在執(zhí)行 connect 函數(shù)時(shí),內(nèi)核選擇端口的情況大致說了一遍,為了讓大家更明白客戶端端口的選擇過程,我畫了一流程圖。

總結(jié)TCP 和 UDP 可以同時(shí)綁定相同的端口嗎?

可以的。

TCP 和 UDP 傳輸協(xié)議,在內(nèi)核中是由兩個(gè)完全獨(dú)立的軟件模塊實(shí)現(xiàn)的。

當(dāng)主機(jī)收到數(shù)據(jù)包后,可以在 IP 包頭的「協(xié)議號(hào)」字段知道該數(shù)據(jù)包是 TCP/UDP,所以可以根據(jù)這個(gè)信息確定送給哪個(gè)模塊(TCP/UDP)處理,送給 TCP/UDP 模塊的報(bào)文根據(jù)「端口號(hào)」確定送給哪個(gè)應(yīng)用程序處理。

因此, TCP/UDP 各自的端口號(hào)也相互獨(dú)立,互不影響。

多個(gè) TCP 服務(wù)進(jìn)程可以同時(shí)綁定同一個(gè)端口嗎?

如果兩個(gè) TCP 服務(wù)進(jìn)程同時(shí)綁定的 IP 地址和端口都相同,那么執(zhí)行 bind() 時(shí)候就會(huì)出錯(cuò),錯(cuò)誤是“Address already in use”。

如果兩個(gè) TCP 服務(wù)進(jìn)程綁定的端口都相同,而 IP 地址不同,那么執(zhí)行 bind()不會(huì)出錯(cuò)。

如何解決服務(wù)端重啟時(shí),報(bào)錯(cuò)“Address already in use”的問題?

當(dāng)我們重啟 TCP 服務(wù)進(jìn)程的時(shí)候,意味著通過服務(wù)器端發(fā)起了關(guān)閉連接操作,于是就會(huì)經(jīng)過四次揮手,而對(duì)于主動(dòng)關(guān)閉方,會(huì)在 TIME_WAIT 這個(gè)狀態(tài)里停留一段時(shí)間,這個(gè)時(shí)間大約為 2MSL。

當(dāng) TCP 服務(wù)進(jìn)程重啟時(shí),服務(wù)端會(huì)出現(xiàn) TIME_WAIT 狀態(tài)的連接,TIME_WAIT 狀態(tài)的連接使用的 IP+PORT 仍然被認(rèn)為是一個(gè)有效的 IP+PORT 組合,相同機(jī)器上不能夠在該 IP+PORT 組合上進(jìn)行綁定,那么執(zhí)行 bind() 函數(shù)的時(shí)候,就會(huì)返回了 Address already in use 的錯(cuò)誤。

要解決這個(gè)問題,我們可以對(duì) socket 設(shè)置 SO_REUSEADDR 屬性。

這樣即使存在一個(gè)和綁定 IP+PORT一樣的TIME_WAIT 狀態(tài)的連接,依然可以正常綁定成功,因此可以正常重啟成功。

客戶端的端口可以重復(fù)使用嗎?

在客戶端執(zhí)行 connect 函數(shù)的時(shí)候,只要客戶端連接的服務(wù)器不是同一個(gè),內(nèi)核允許端口重復(fù)使用。

TCP 連接是由四元組(源IP地址,源端口,目的IP地址,目的端口)唯一確認(rèn)的,那么只要四元組中其中一個(gè)元素發(fā)生了變化,那么就表示不同的 TCP 連接的。

所以,如果客戶端已使用端口 64992 與服務(wù)端 A 建立了連接,那么客戶端要與服務(wù)端 B 建立連接,還是可以使用端口 64992 的,因?yàn)閮?nèi)核是通過四元祖信息來(lái)定位一個(gè) TCP 連接的,并不會(huì)因?yàn)榭蛻舳说亩丝谔?hào)相同,而導(dǎo)致連接沖突的問題。

客戶端 TCP 連接 TIME_WAIT 狀態(tài)過多,會(huì)導(dǎo)致端口資源耗盡而無(wú)法建立新的連接嗎?

要看客戶端是否都是與同一個(gè)服務(wù)器(目標(biāo)地址和目標(biāo)端口一樣)建立連接。

如果客戶端都是與同一個(gè)服務(wù)器(目標(biāo)地址和目標(biāo)端口一樣)建立連接,那么如果客戶端 TIME_WAIT 狀態(tài)的連接過多,當(dāng)端口資源被耗盡,就無(wú)法與這個(gè)服務(wù)器再建立連接了。即使在這種狀態(tài)下,還是可以與其他服務(wù)器建立連接的,只要客戶端連接的服務(wù)器不是同一個(gè),那么端口是重復(fù)使用的。

如何解決客戶端 TCP 連接 TIME_WAIT 過多,導(dǎo)致無(wú)法與同一個(gè)服務(wù)器建立連接的問題?

打開 net.ipv4.tcp_tw_reuse 這個(gè)內(nèi)核參數(shù)。

因?yàn)殚_啟了這個(gè)內(nèi)核參數(shù)后,客戶端調(diào)用 connect 函數(shù)時(shí),如果選擇到的端口,已經(jīng)被相同四元組的連接占用的時(shí)候,就會(huì)判斷該連接是否處于 TIME_WAIT 狀態(tài)。

如果該連接處于 TIME_WAIT 狀態(tài)并且 TIME_WAIT 狀態(tài)持續(xù)的時(shí)間超過了 1 秒,那么就會(huì)重用這個(gè)連接,然后就可以正常使用該端口了。

標(biāo)簽: