<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          最后一天,繼續(xù)卷!

          共 3044字,需瀏覽 7分鐘

           ·

          2022-01-02 08:49

          ?

          ?

          大家好,我是小林。

          2021年最后一天,我也要卷下。
          早上有個(gè)讀者問了我圖解網(wǎng)絡(luò) PDF 里的問題:
          就是他不明白「為什么 TCP 三次握手期間,為什么客戶端和服務(wù)端的初始化序列號(hào)要求不一樣的呢?
          我的圖解網(wǎng)絡(luò) PDF 在解釋這個(gè)原因的時(shí)候,就寫的幾句話,可能會(huì)讓人看的很懵逼。
          后來,我跟他交流半個(gè)小時(shí),終于把他講明白了。
          我是一步一步把他講明白的,我覺得應(yīng)該有不少人會(huì)有類似的問題,所以今天在肝一篇!

          正文

          為什么 TCP 三次握手期間,為什么客戶端和服務(wù)端的初始化序列號(hào)要求不一樣的呢?
          主要原因是為了防止歷史報(bào)文被下一個(gè)相同四元組的連接接收。
          TCP 四次揮手中的 TIME_WAIT 狀態(tài)不是會(huì)持續(xù) 2 MSL 時(shí)長,歷史報(bào)文不是早就在網(wǎng)絡(luò)中消失了嗎?
          是的,如果能正常四次揮手,由于 TIME_WAIT 狀態(tài)會(huì)持續(xù) ?2 MSL 時(shí)長,歷史報(bào)文會(huì)在下一個(gè)連接之前就會(huì)自然消失。
          但是來了,我們并不能保證每次連接都能通過四次揮手來正常關(guān)閉連接。
          假設(shè)每次建立連接,客戶端和服務(wù)端的初始化序列號(hào)都是從 0 開始:
          過程如下:
          • 客戶端和服務(wù)端建立一個(gè) TCP 連接,在客戶端發(fā)送數(shù)據(jù)包被網(wǎng)絡(luò)阻塞了,而此時(shí)服務(wù)端的進(jìn)程重啟了,于是就會(huì)發(fā)送 RST 報(bào)文來斷開連接。

          • 緊接著,客戶端又與服務(wù)端建立了與上一個(gè)連接相同四元組的連接;

          • 在新連接建立完成后,上一個(gè)連接中被網(wǎng)絡(luò)阻塞的數(shù)據(jù)包正好抵達(dá)了服務(wù)端,剛好該數(shù)據(jù)包的序列號(hào)正好是在服務(wù)端的接收窗口內(nèi),所以該數(shù)據(jù)包會(huì)被服務(wù)端正常接收,就會(huì)造成數(shù)據(jù)錯(cuò)亂。

          可以看到,如果每次建立連接,客戶端和服務(wù)端的初始化序列號(hào)都是一樣的話,很容易出現(xiàn)歷史報(bào)文被下一個(gè)相同四元組的連接接收的問題。
          客戶端和服務(wù)端的初始化序列號(hào)不一樣不是也會(huì)發(fā)生這樣的事情嗎?
          是的,即使客戶端和服務(wù)端的初始化序列號(hào)不一樣,也會(huì)存在收到歷史報(bào)文的可能。
          但是我們要清楚一點(diǎn),歷史報(bào)文能否被對(duì)方接收,還要看該歷史報(bào)文的序列號(hào)是否正好在對(duì)方接收窗口內(nèi),如果不在就會(huì)丟棄,如果在才會(huì)接收。
          如果每次建立連接客戶端和服務(wù)端的初始化序列號(hào)都「不一樣」,就有大概率因?yàn)闅v史報(bào)文的序列號(hào)「不在」對(duì)方接收窗口,從而很大程度上避免了歷史報(bào)文,比如下圖:
          相反,如果每次建立連接客戶端和服務(wù)端的初始化序列號(hào)都「一樣」,就有大概率遇到歷史報(bào)文的序列號(hào)剛「好在」對(duì)方的接收窗口內(nèi),從而導(dǎo)致歷史報(bào)文被新連接成功接收。
          所以,每次初始化序列號(hào)不一樣能夠很大程度上避免歷史報(bào)文被下一個(gè)相同四元組的連接接收,注意是很大程度上,并不是完全避免了。
          那客戶端和服務(wù)端的初始化序列號(hào)都是隨機(jī)的,那還是有可能隨機(jī)成一樣的呀?
          RFC793 提到初始化序列號(hào) ISN 隨機(jī)生成算法:ISN = M + F(localhost, localport, remotehost, remoteport)。
          • M是一個(gè)計(jì)時(shí)器,這個(gè)計(jì)時(shí)器每隔4毫秒加1。

          • F 是一個(gè) Hash 算法,根據(jù)源IP、目的IP、源端口、目的端口生成一個(gè)隨機(jī)數(shù)值,要保證 hash 算法不能被外部輕易推算得出。

          可以看到,隨機(jī)數(shù)是會(huì)基于時(shí)鐘計(jì)時(shí)器遞增的,基本不可能會(huì)隨機(jī)成一樣的初始化序列號(hào)。
          懂了,客戶端和服務(wù)端初始化序列號(hào)都是隨機(jī)生成的話,就能避免連接接收歷史報(bào)文了。
          是的,但是也不是完全避免了。
          為了能更好的理解這個(gè)原因,我們先來了解序列號(hào)(SEQ)和初始序列號(hào)(ISN)。
          • 序列號(hào),是 TCP 一個(gè)頭部字段,標(biāo)識(shí)了 TCP 發(fā)送端到 TCP 接收端的數(shù)據(jù)流的一個(gè)字節(jié),因?yàn)?TCP 是面向字節(jié)流的可靠協(xié)議,為了保證消息的順序性和可靠性,TCP 為每個(gè)傳輸方向上的每個(gè)字節(jié)都賦予了一個(gè)編號(hào),以便于傳輸成功后確認(rèn)、丟失后重傳以及在接收端保證不會(huì)亂序。序列號(hào)是一個(gè) 32 位的無符號(hào)數(shù),因此在到達(dá) 4G 之后再循環(huán)回到 0

          • 初始序列號(hào),在 TCP 建立連接的時(shí)候,客戶端和服務(wù)端都會(huì)各自生成一個(gè)初始序列號(hào),它是基于時(shí)鐘生成的一個(gè)隨機(jī)數(shù),來保證每個(gè)連接都擁有不同的初始序列號(hào)。初始化序列號(hào)可被視為一個(gè) 32 位的計(jì)數(shù)器,該計(jì)數(shù)器的數(shù)值每 4 微秒加 1,循環(huán)一次需要 4.55 小時(shí)

          給大家抓了一個(gè)包,下圖中的 Seq 就是序列號(hào),其中紅色框住的分別是客戶端和服務(wù)端各自生成的初始序列號(hào)。
          圖片
          通過前面我們知道,序列號(hào)和初始化序列號(hào)并不是無限遞增的,會(huì)發(fā)生回繞為初始值的情況,這意味著無法根據(jù)序列號(hào)來判斷新老數(shù)據(jù)
          不要以為序列號(hào)的上限值是 4GB,就以為很大,很難發(fā)生回繞。在一個(gè)速度足夠快的網(wǎng)絡(luò)中傳輸大量數(shù)據(jù)時(shí),序列號(hào)的回繞時(shí)間就會(huì)變短。如果序列號(hào)回繞的時(shí)間極短,我們就會(huì)再次面臨之前延遲的報(bào)文抵達(dá)后序列號(hào)依然有效的問題。
          為了解決這個(gè)問題,就需要有 TCP 時(shí)間戳。tcp_timestamps 參數(shù)是默認(rèn)開啟的,開啟了 tcp_timestamps 參數(shù),TCP 頭部就會(huì)使用時(shí)間戳選項(xiàng),它有兩個(gè)好處,一個(gè)是便于精確計(jì)算 RTT ,另一個(gè)是能防止序列號(hào)回繞(PAWS)
          試看下面的示例,假設(shè) TCP 的發(fā)送窗口是 1 GB,并且使用了時(shí)間戳選項(xiàng),發(fā)送方會(huì)為每個(gè) TCP 報(bào)文分配時(shí)間戳數(shù)值,我們假設(shè)每個(gè)報(bào)文時(shí)間加 1,然后使用這個(gè)連接傳輸一個(gè) 6GB 大小的數(shù)據(jù)流。
          32 位的序列號(hào)在時(shí)刻 D 和 E 之間回繞。假設(shè)在時(shí)刻B有一個(gè)報(bào)文丟失并被重傳,又假設(shè)這個(gè)報(bào)文段在網(wǎng)絡(luò)上繞了遠(yuǎn)路并在時(shí)刻 F 重新出現(xiàn)。如果 TCP 無法識(shí)別這個(gè)繞回的報(bào)文,那么數(shù)據(jù)完整性就會(huì)遭到破壞。
          使用時(shí)間戳選項(xiàng)能夠有效的防止上述問題,如果丟失的報(bào)文會(huì)在時(shí)刻 F 重新出現(xiàn),由于它的時(shí)間戳為 2,小于最近的有效時(shí)間戳(5 或 6),因此防回繞序列號(hào)算法(PAWS)會(huì)將其丟棄。
          防回繞序列號(hào)算法要求連接雙方維護(hù)最近一次收到的數(shù)據(jù)包的時(shí)間戳(Recent TSval),每收到一個(gè)新數(shù)據(jù)包都會(huì)讀取數(shù)據(jù)包中的時(shí)間戳值跟 Recent TSval 值做比較,如果發(fā)現(xiàn)收到的數(shù)據(jù)包中時(shí)間戳不是遞增的,則表示該數(shù)據(jù)包是過期的,就會(huì)直接丟棄這個(gè)數(shù)據(jù)包
          懂了,客戶端和服務(wù)端的初始化序列號(hào)都是隨機(jī)生成,能很大程度上避免歷史報(bào)文被下一個(gè)相同四元組的連接接收,然后又引入時(shí)間戳的機(jī)制,從而完全避免了歷史報(bào)文被接收的問題。
          嗯嗯,沒錯(cuò)。

          好了,就卷到這了。
          自從圖解網(wǎng)絡(luò) PDF 發(fā)布之后,小林又根據(jù)讀者面試時(shí)遇到的網(wǎng)絡(luò)問題寫了很多篇網(wǎng)絡(luò)相關(guān)的文章,這部分內(nèi)容是可以考慮加入到圖解網(wǎng)絡(luò) PDF 里的。
          而且之前的網(wǎng)絡(luò) PDF 有很多讀者幫我勘誤了很多錯(cuò)別字,所以明年得找個(gè)時(shí)間重新整理出一個(gè)新版本的圖解網(wǎng)絡(luò) PDF。
          回想 2021 年出了《圖解網(wǎng)絡(luò)》和《圖解系統(tǒng)》PDF:
          小林的圖解系統(tǒng),大曝光!
          不鴿了,小林的「圖解網(wǎng)絡(luò) 3.0 」發(fā)布!
          經(jīng)常收到很多好消息,比如:
          • 收到讀者的打賞,不管多少錢都是對(duì)小林的最好的認(rèn)可;

          • 收到讀者的感謝,幫助他們面試中擊破了網(wǎng)絡(luò)和系統(tǒng)的八股文面試,我把讀者們的故事,都收錄到了這里:讀者牛逼

          本來計(jì)劃今年年末出《圖解MySQL》和 《圖解Reids》PDF,很可惜沒有完成,這個(gè) flag 倒了。
          沒關(guān)系,倒了就倒了,重新納入 2022 年的計(jì)劃!重新起航!
          感謝大家這一年的支持和陪伴,明年再見!
          ?

          ?

          瀏覽 37
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  免贾观看国产女人高潮 | 亚洲成人性爱 | 欧洲亚洲韩国在线观看 | 在线观看国产视频 | 日日躁夜夜躁狠狠躁麻豆 |