碼仔漫畫:如何跟女朋友 “四次揮手”
本文轉(zhuǎn)載自微信公眾號(hào)「碼個(gè)蛋」,作者碼仔。轉(zhuǎn)載本文請聯(lián)系碼個(gè)蛋公眾號(hào)。
MSL 是 Maximum Segment Lifetime,報(bào)文最大生存時(shí)間,它是任何報(bào)文在網(wǎng)絡(luò)上存在的最長時(shí)間,超過這個(gè)時(shí)間報(bào)文將被丟棄。因?yàn)?TCP 報(bào)文基于是 IP 協(xié)議的,而 IP 頭中有一個(gè) TTL 字段,是 IP 數(shù)據(jù)報(bào)可以經(jīng)過的最大路由數(shù),每經(jīng)過一個(gè)處理他的路由器此值就減 1,當(dāng)此值為 0 則數(shù)據(jù)報(bào)將被丟棄,同時(shí)發(fā)送 ICMP 報(bào)文通知源主機(jī)。
MSL 與 TTL 的區(qū)別:MSL 的單位是時(shí)間,而 TTL 是經(jīng)過路由跳數(shù)。所以 MSL 應(yīng)該要大于等于 TTL 消耗為 0 的時(shí)間,以確保報(bào)文已被自然消亡。
TIME_WAIT 等待 2 倍的 MSL,比較合理的解釋是:網(wǎng)絡(luò)中可能存在來自發(fā)送方的數(shù)據(jù)包,當(dāng)這些發(fā)送方的數(shù)據(jù)包被接收方處理后又會(huì)向?qū)Ψ桨l(fā)送響應(yīng),所以一來一回需要等待 2 倍的時(shí)間。
比如如果被動(dòng)關(guān)閉方?jīng)]有收到斷開連接的最后的 ACK 報(bào)文,就會(huì)觸發(fā)超時(shí)重發(fā) Fin 報(bào)文,另一方接收到 FIN 后,會(huì)重發(fā) ACK 給被動(dòng)關(guān)閉方, 一來一去正好 2 個(gè) MSL。
2MSL 的時(shí)間是從客戶端接收到 FIN 后發(fā)送 ACK 開始計(jì)時(shí)的。如果在 TIME-WAIT 時(shí)間內(nèi),因?yàn)榭蛻舳说?ACK 沒有傳輸?shù)椒?wù)端,客戶端又接收到了服務(wù)端重發(fā)的 FIN 報(bào)文,那么 2MSL 時(shí)間將重新計(jì)時(shí)。
在 Linux 系統(tǒng)里 2MSL 默認(rèn)是 60 秒,那么一個(gè) MSL 也就是 30 秒。Linux 系統(tǒng)停留在 TIME_WAIT 的時(shí)間為固定的 60 秒。
其定義在 Linux 內(nèi)核代碼里的名稱為 TCP_TIMEWAIT_LEN:
- #define TCP_TIMEWAIT_LEN (60*HZ) /* how long to wait to destroy TIME-WAIT
- state, about 60 seconds */
如果要修改 TIME_WAIT 的時(shí)間長度,只能修改 Linux 內(nèi)核代碼里 TCP_TIMEWAIT_LEN 的值,并重新編譯 Linux 內(nèi)核。
需要 TIME-WAIT 狀態(tài),主要是兩個(gè)原因:
- 防止具有相同「四元組」的「舊」數(shù)據(jù)包被收到;
- 保證「被動(dòng)關(guān)閉連接」的一方能被正確的關(guān)閉,即保證最后的 ACK 能讓被動(dòng)關(guān)閉方接收,從而幫助其正常關(guān)閉;