偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

為什么 TCP 需要 TIME_WAIT,你知道嗎 ?

網(wǎng)絡(luò)
當(dāng)我們在本地 (客戶端) 啟動(dòng)并發(fā)壓力測試時(shí),通常會(huì)設(shè)置成百上千的并發(fā)連接去訪問服務(wù)端接口,這些連接會(huì)快速且大量消耗 TCP 連接資源,每個(gè)連接在完成接口請求后會(huì)理解進(jìn)入 TIME_WAIT 狀態(tài)。

TCP 狀態(tài)機(jī)

下圖所示的狀態(tài)機(jī)展示了,通信雙方建立 TCP 連接之后的狀態(tài)轉(zhuǎn)換過程。

圖片來源: tcpipguide.com

通信雙方主動(dòng)發(fā)起關(guān)閉連接的一端,存在 TIME_WAIT 狀態(tài),被動(dòng)接受關(guān)閉連接的一端,會(huì)進(jìn)入 CLOSE_WAIT 狀態(tài)。

處于 TIME_WAIT 狀態(tài)的一端,主要浪費(fèi)兩種資源:

  • 端口號 (主要資源)
  • 系統(tǒng)資源 (文件描述符、內(nèi)存資源、CPU 資源、線程資源),對于現(xiàn)代化硬件來說,這點(diǎn)資源可以忽略不計(jì)

兩個(gè)問題

這里以客戶端主動(dòng)關(guān)閉連接為例,先來看下經(jīng)典的 “四次揮手” 過程:

圖片來源: tcpipguide.com

  • 第一次揮手: 當(dāng)客戶端沒有要發(fā)送的數(shù)據(jù)時(shí),向服務(wù)端發(fā)送 FIN 消息,客戶端進(jìn)入 FIN_WAIT_1 狀態(tài)
  • 第二次揮手: 服務(wù)端收到客戶端的 FIN 消息之后,進(jìn)入 CLOSE_WAIT 狀態(tài),然后向客戶端發(fā)送 ACK 消息,客戶端收到 ACK 消息之后進(jìn)入 FIN_WAIT_2 狀態(tài)
  • 第三次揮手: 當(dāng)服務(wù)端沒有要發(fā)送的數(shù)據(jù)時(shí),向客戶端發(fā)送 FIN 消息,然后服務(wù)端進(jìn)入 LAST_ACK 狀態(tài)
  • 第四次揮手: 客戶端收到服務(wù)端的 FIN 消息之后,進(jìn)入 TIME_WAIT 狀態(tài),然后向服務(wù)端發(fā)送 ACK 消息,服務(wù)端收到 ACK 消息進(jìn)入 CLOSED 狀態(tài)
  • 客戶端等大等待 2 個(gè) MSL 時(shí)間后進(jìn)入 CLOSED 狀態(tài)

客戶端需要維護(hù)一個(gè) TIME_WAIT 狀態(tài)長達(dá) 2 個(gè) MSL 時(shí)間,以 Linux 5.0 代碼為例,也就是 2 分鐘。

// https://github.com/torvalds/linux/blob/1c163f4c7b3f621efff9b28a47abb36f7378d783/include/net/tcp.h#L121

#define TCP_TIMEWAIT_LEN (60*HZ) /* how long to wait to destroy TIME-WAIT state, about 60 seconds */

為什么是 2 個(gè) MSL 時(shí)間呢?

因?yàn)榘l(fā)送方要考慮數(shù)據(jù)報(bào)文 從發(fā)送方到接收方的 MSL, 反過來說,接收方也要考慮 ACK 報(bào)文從接收方到發(fā)送方的 MSL,所以一共是 2 個(gè) MSL (通信雙方各一個(gè))。

之所以采用這種機(jī)制,主要是為了避免發(fā)生下面兩個(gè)問題:

  • 防止被動(dòng)關(guān)閉連接的一端,延遲的數(shù)據(jù)被后續(xù)使用 相同四元組的 TCP 連接 接收
  • 防止被動(dòng)關(guān)閉連接的一端,發(fā)出的 FIN 消息沒有收到對應(yīng)的 ACK 消息,而在新連接到來的時(shí)候發(fā)送 RST 消息

下面就這兩個(gè)問題來進(jìn)行分析說明。

第一個(gè)問題

防止被動(dòng)關(guān)閉連接的一端,延遲的數(shù)據(jù)被后續(xù)使用 相同四元組的新連接 接收。

簡單來說,就是防止舊的 TCP 連接,因?yàn)檠舆t到達(dá)的報(bào)文,而干擾到了復(fù)用相同四元組的新連接。

四元組客戶端客戶端端口服務(wù)端服務(wù)端端口

下面來舉例說一下什么場景下會(huì)出現(xiàn)這種情況。

延遲到達(dá)的報(bào)文干擾到了新連接

  • 假設(shè)在客戶端在主動(dòng)關(guān)閉連接前,服務(wù)端發(fā)送了一個(gè) seq = 1001 的數(shù)據(jù)包 A,但是由于網(wǎng)絡(luò)原因一直沒有送達(dá)到客戶端 (也就是以說,該數(shù)據(jù)包延遲了)
  • 如果客戶端沒有 TIME_WAIT 狀態(tài),那么客戶端第四次揮手后,此時(shí)客戶端會(huì)直接進(jìn)入 CLOSED 狀態(tài)
  • 延遲的數(shù)據(jù)包 A 依然沒有到來
  • 這時(shí)客戶端又向服務(wù)端發(fā)起新的連接,很巧的是,這個(gè)新連接和剛才 (已關(guān)閉) 的舊連接使用了同樣的端口 (復(fù)用),于是新連接和舊連接的四元組變成了一樣的
  • 新連接建立完成后,舊連接上面的延遲數(shù)據(jù)包 A 到了 (新連接),這時(shí)就會(huì)產(chǎn)生嚴(yán)重的問題 ...

通過 TIME_WAIT 狀態(tài),發(fā)起主動(dòng)關(guān)閉連接的一端會(huì)等待 2 個(gè) MSL 時(shí)間,這個(gè)時(shí)間足夠長,可以最大限度消除延遲的數(shù)據(jù)包可能對新 (復(fù)用端口) 的連接造成影響, TIME_WAIT 狀態(tài)下接收到的延遲數(shù)據(jù)包會(huì)被直接丟棄。

這里考慮一個(gè)極端的 (小概率) 問題: 經(jīng)過 2 個(gè) MSL 時(shí)間之后,延遲的數(shù)據(jù)包 A 到達(dá)了,并且其 Seq 正好位于新連接的接收窗口內(nèi),那么新連接 (TCP 傳輸層) 會(huì)直接將整個(gè)數(shù)據(jù)包轉(zhuǎn)交到上層應(yīng)用嗎?

根據(jù)應(yīng)用層安全 (是否加密) 程度,分為兩種情況:

  • 未加密,那么就會(huì)干擾應(yīng)用數(shù)據(jù),例如源數(shù)據(jù)為 “我的頭像牛 X 嗎?”,因?yàn)檠舆t的數(shù)據(jù)包,在 頭 字后面插入了一個(gè)逗號,變成了 “我的頭,像牛 X 嗎?”
  • 已加密 (例如使用了 HTTPS),TLS 會(huì)校驗(yàn)數(shù)據(jù)完整性,那么顯然數(shù)據(jù)包 A 是無法通過校驗(yàn)的,然后被直接丟棄,HTTPS 連接就此中斷

第二個(gè)問題

防止被動(dòng)關(guān)閉連接的一端,發(fā)出的 FIN 消息沒有收到對應(yīng)的 ACK 消息,而在新連接到來的時(shí)候發(fā)送 RST 消息。

簡單來說,就是防止舊的 TCP 連接在第四次揮手中發(fā)出的 ACK 消息沒有被對端收到,而導(dǎo)致復(fù)用相同四元組的新連接在和對端建立連接時(shí)被拒絕。

下面來舉例說一下什么場景下會(huì)出現(xiàn)這種情況。

新連接建立時(shí)被 RST 消息拒絕

  • 客戶端第四次揮手時(shí)向服務(wù)端發(fā)送 ACK 消息,但是這個(gè) ACK 消息一直因?yàn)榫W(wǎng)絡(luò)原因一直未送達(dá),所以服務(wù)端的狀態(tài)停留在了 LAST-ACK,而不是正常的 CLOSED 狀態(tài)
  • 如果客戶端沒有 TIME_WAIT 狀態(tài),那么客戶端第四次揮手后,此時(shí)客戶端會(huì)直接進(jìn)入 CLOSED 狀態(tài),但是此時(shí)服務(wù)端認(rèn)為這條連接依然是有效的 (還未徹底斷開)
  • 這時(shí)客戶端又向服務(wù)端發(fā)起新的連接,很巧的是,這個(gè)新連接和剛才 (已關(guān)閉) 的舊連接使用了同樣的端口 (復(fù)用),于是新連接和舊連接的四元組變成了一樣的
  • 服務(wù)端收到了客戶端的新鏈接建立時(shí)發(fā)送的 SYNC 消息,在服務(wù)端看來,這其實(shí)是一條舊的有效連接 (因?yàn)樾逻B接和舊連接的四元組是一樣的),所以會(huì)直接返回 RST 消息,拒絕新連接的建立 (連接過程到此終止)

通過 TIME_WAIT 狀態(tài),發(fā)起主動(dòng)關(guān)閉連接的一端會(huì)等待 2 個(gè) MSL 時(shí)間,這個(gè)時(shí)間足夠長,那么服務(wù)端可能會(huì)出現(xiàn)兩種情況:

  • 收到了客戶端的 ACK 消息,正常關(guān)閉連接,進(jìn)入 CLOSE 狀態(tài)
  • 沒有收到客戶端的 ACK 消息,重新發(fā)送 FIN 消息關(guān)閉連接并等待新的 ACK 消息 (重新執(zhí)行第三次、四次揮手)

問題場景

分析完了 TIME_WAIT 狀態(tài)的作用之外,什么場景下會(huì)出現(xiàn)大量的 TIME_WAIT 狀態(tài)連接呢?

通信雙方主動(dòng)發(fā)起關(guān)閉連接的一端,存在 TIME_WAIT 狀態(tài),最經(jīng)典的場景就是 并發(fā)壓力測試。

當(dāng)我們在本地 (客戶端) 啟動(dòng)并發(fā)壓力測試時(shí),通常會(huì)設(shè)置成百上千的并發(fā)連接去訪問服務(wù)端接口,這些連接會(huì)快速且大量消耗 TCP 連接資源,每個(gè)連接在完成接口請求后會(huì)理解進(jìn)入 TIME_WAIT 狀態(tài)。

例如,在 Linux 系統(tǒng)中,可以使用 netstat 命令來查看各個(gè)不同狀態(tài)的網(wǎng)絡(luò)連接:

$ netstat -ant | grep TIME_WAIT

# 輸出如下
tcp6       0      0 1.1.1.1:443          127.0.0.1:59490         TIME_WAIT
tcp6       0      0 1.1.1.1:443          127.0.0.1:59472         TIME_WAIT
tcp6       0      0 1.1.1.1:443          127.0.0.1:59480         TIME_WAIT
tcp6       0      0 1.1.1.1:443          127.0.0.1:59514         TIME_WAIT
tcp6       0      0 1.1.1.1:443          127.0.0.1:59484         TIME_WAIT
tcp6       0      0 1.1.1.1:443          127.0.0.1:59520         TIME_WAIT

這類問題如何解決,后面再專門寫一篇高性能網(wǎng)絡(luò)編程中 TCP 調(diào)優(yōu)的文章 :-)。

? 思考

如果系統(tǒng)中出現(xiàn)大量的 CLOSE_WAIT 狀態(tài)連接,可能原因是什么呢?如何解決?

責(zé)任編輯:趙寧寧 來源: 洋芋編程
相關(guān)推薦

2020-11-17 08:30:06

LinuxSwapping 設(shè)計(jì)

2025-06-05 01:11:00

2023-11-02 10:22:29

gRPC后端通信

2024-10-09 08:19:35

2017-10-16 13:45:04

2015-03-27 10:18:25

TCP協(xié)議CLOSE_WAIT狀服務(wù)器異常

2020-08-06 10:12:20

TCP連接網(wǎng)絡(luò)協(xié)議

2024-04-30 09:02:48

2023-12-20 08:23:53

NIO組件非阻塞

2021-11-09 10:28:12

手機(jī)內(nèi)存技術(shù)

2024-07-30 08:22:47

API前端網(wǎng)關(guān)

2024-04-07 00:00:03

2024-10-10 16:53:53

守護(hù)線程編程

2024-08-20 08:29:55

2024-11-08 09:48:38

異步編程I/O密集

2025-02-18 08:11:17

2022-11-28 00:04:17

2024-01-15 12:16:37

2024-01-19 19:22:45

TCPTIME_WAIT

2024-07-26 21:53:59

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號