因特網(wǎng)無疑是人類有史以來最偉大的設(shè)計(jì),它互聯(lián)了全球數(shù)億臺(tái)計(jì)算機(jī)、通訊設(shè)備,即便位于地球兩端的用戶也可在頃刻間完成通訊。
可以說『協(xié)議』是支撐這么一個(gè)龐大而復(fù)雜的系統(tǒng)有條不紊運(yùn)作的核心,而所謂『協(xié)議』就是通訊雙方所必須遵守的規(guī)則,在這種規(guī)則下,不同的數(shù)據(jù)報(bào)可能被解析為不同的響應(yīng)動(dòng)作。
簡而言之,『協(xié)議』就是指如果發(fā)送和接收方按照這個(gè)規(guī)則進(jìn)行數(shù)據(jù)報(bào)文的發(fā)送,即可在基本的數(shù)據(jù)傳輸之上得到某些特殊的功能或服務(wù),否則你的數(shù)據(jù)別人是不認(rèn)識(shí)的。例如:遵循 TCP 協(xié)議的兩端,可以在不可靠的網(wǎng)絡(luò)傳輸中得到可靠的數(shù)據(jù)傳輸能力。
整個(gè)計(jì)算機(jī)網(wǎng)絡(luò)是分層的,有七層模型,也有五層模型,個(gè)人覺得五層模型更利于理解。我們從上至下的介紹這五個(gè)層,它們分別是,應(yīng)用層,運(yùn)輸層,網(wǎng)絡(luò)層,數(shù)據(jù)鏈路層和物理層。
『應(yīng)用層』算是距離用戶最近的一層了,主機(jī)上的一個(gè)個(gè)的進(jìn)程就構(gòu)成了『應(yīng)用層』。比如你在你的瀏覽器地址欄輸入了 「www.baidu.com」,你的瀏覽器在應(yīng)用層會(huì)做哪些事情呢?
首先瀏覽器會(huì)使用 DNS 協(xié)議返回域名「www.baidu.com」所對(duì)應(yīng)的 IP 地址,關(guān)于 DNS 我們待會(huì)詳細(xì)介紹。
接著,應(yīng)用層決定創(chuàng)建一個(gè)『TCP 套接字』,然后將這個(gè)請(qǐng)求動(dòng)作封裝成一個(gè) Http 數(shù)據(jù)報(bào)并推入套接字中。
套接字分為兩種類型,『TCP 套接字』和『UDP 套接字』,應(yīng)用層同時(shí)可能會(huì)有幾十個(gè)數(shù)據(jù)報(bào)的發(fā)出,而運(yùn)輸層也會(huì)收到所有的響應(yīng)報(bào)文,那么它該如何區(qū)分這些報(bào)文到底是誰的響應(yīng)報(bào)文呢?
而套接字就是用于區(qū)分各個(gè)應(yīng)用層應(yīng)用的,往往由端口號(hào)和 IP 地址進(jìn)行標(biāo)識(shí),運(yùn)輸層只要查看響應(yīng)報(bào)文的源端口號(hào)和 IP 地址就能夠知道該將報(bào)文推送給哪個(gè)套接字了。
當(dāng)一個(gè)應(yīng)用層數(shù)據(jù)報(bào)被推動(dòng)進(jìn)套接字之后,應(yīng)用層的所有工作也算是全部完成了,關(guān)于后續(xù)報(bào)文的去向,它已經(jīng)不用管了。
這里還要說明一點(diǎn)的是,『TCP 套接字』和『UDP 套接字』兩者本質(zhì)上的區(qū)別在于,前者保證數(shù)據(jù)報(bào)可靠地到達(dá)目的地,但是必然耗時(shí),而后者不保證數(shù)據(jù)報(bào)一定能到達(dá)目的地,但是速度快,這也是應(yīng)用層協(xié)議在選擇運(yùn)輸層協(xié)議的時(shí)候需要考慮的一點(diǎn)。
關(guān)于 TCP 和 UDP,我們后續(xù)還會(huì)繼續(xù)說,下面我們看看域名解析協(xié)議 DNS 是如何運(yùn)作的,它是如何將一個(gè)域名解析返回它的 IP 地址的。
DNS 原理
首先明確一點(diǎn)的是,DNS 是一個(gè)應(yīng)用層協(xié)議,并且它選擇的運(yùn)輸層協(xié)議是 UDP,所以你的域名解析過程一般會(huì)很快,但也會(huì)經(jīng)常出現(xiàn)解析失敗的情況,然而刷新一下又好了。
在 DNS 服務(wù)器上,域名和它所對(duì)應(yīng)的 IP 地址存儲(chǔ)為一條記錄,而所有的記錄都不可能只存儲(chǔ)在一臺(tái)服務(wù)器上,我相信無論多么強(qiáng)大的服務(wù)器都扛不住全球上億次的并發(fā)量吧。
大致來說,有三種類型的 DNS 服務(wù)器,根 DNS 服務(wù)器,頂級(jí)域 DNS 服務(wù)器和權(quán)威 DNS 服務(wù)器。
其中,頂級(jí)域 DNS 服務(wù)器主要負(fù)責(zé)諸如 com、org、net、edu、gov 等頂級(jí)域名。
根 DNS 服務(wù)器存儲(chǔ)了所有頂級(jí)域 DNS 服務(wù)器的 IP 地址,也就是說你可以通過根服務(wù)器找到頂級(jí)域服務(wù)器。例如:「www.baidu.com」,根服務(wù)器會(huì)返回所有維護(hù) com 這個(gè)頂級(jí)域服務(wù)器的 IP 地址。
然后你任意選擇其中一個(gè)頂級(jí)域服務(wù)器,請(qǐng)求該頂級(jí)域服務(wù)器,該頂級(jí)域服務(wù)器拿到域名后應(yīng)當(dāng)能夠做出判斷并給出負(fù)責(zé)當(dāng)前域的權(quán)威服務(wù)器地址,以百度為例的話,頂級(jí)域服務(wù)器將返回所有負(fù)責(zé) baidu 這個(gè)域的權(quán)威服務(wù)器地址。
于是你可以任意選擇其中一個(gè)權(quán)威服務(wù)器地址,向它繼續(xù)查詢 「www.baidu.com」 的具體 IP 地址,最終權(quán)威服務(wù)器會(huì)返回給你具體的 IP 地址。
至此,我們簡單描述了一個(gè)域名解析的大致過程,還有一些細(xì)節(jié)之處并未提及,我們等會(huì)會(huì)通過一個(gè)實(shí)例來完整的看一下,下面描述一個(gè)非常重要的概念。
整個(gè) DNS 解析過程中,有一個(gè)非常核心的人物我們一直沒介紹它,它就像主機(jī)的『助理』一樣,幫助主機(jī)查詢域名的 IP 地址。它叫做『本地 DNS 服務(wù)器』。
大家每次通過 DHCP 動(dòng)態(tài)獲取 IP 地址的時(shí)候,這一點(diǎn)后文會(huì)說。其實(shí)路由器不僅給你返回了 IP 地址,還會(huì)告訴你一個(gè) DNS 服務(wù)器地址,這個(gè)就是你的本地 DNS 服務(wù)器地址,也就是說,你的所有域名解析請(qǐng)求只要告訴它就行了,它會(huì)幫你查并返回結(jié)果給你的。
除此之外,本地 DNS 服務(wù)器往往是具有緩存功能的,通常兩天內(nèi)的記錄都會(huì)被緩存,所以大部分時(shí)候你是感覺不到域名解析過程的,因?yàn)橥褪菑木彺胬锬玫模浅?臁?/p>
下面我們看一個(gè)簡單的案例:
網(wǎng)上找的一個(gè)圖,自己畫實(shí)在太費(fèi)時(shí)間了,但足以說明問題,現(xiàn)在假設(shè)請(qǐng)求 「www.xx.com」 。
①:主機(jī)向負(fù)責(zé)自己的本地 DNS 發(fā)送查詢報(bào)文,如果本地服務(wù)器緩存中有,將直接返回結(jié)果
②:本地服務(wù)器發(fā)現(xiàn)緩存中沒有,于是從內(nèi)置在內(nèi)部的根服務(wù)器列表中選一個(gè)發(fā)送查詢報(bào)文
③:根服務(wù)器解析一下后綴名,告訴本地服務(wù)器負(fù)責(zé) .com 的所有頂級(jí)服務(wù)器列表
④:本地服務(wù)器選擇一個(gè)頂級(jí)域服務(wù)器繼續(xù)查詢,.com 域服務(wù)器拿到域名后繼續(xù)解析,返回負(fù)責(zé) .xx 域的所有權(quán)威服務(wù)器列表
⑥:本地服務(wù)器從返回的權(quán)威服務(wù)器之一再次發(fā)送查詢報(bào)文,最終會(huì)從某一個(gè)權(quán)威服務(wù)器上得到具體的 IP 地址
⑧:向主機(jī)返回結(jié)果
其實(shí)整個(gè) DNS 報(bào)文的發(fā)送與響應(yīng)過程都是要走我們的五層協(xié)議的,只是這里重點(diǎn)在于理解 DNS 協(xié)議本身,所以并未提及其他層的具體細(xì)節(jié),這里的強(qiáng)調(diào)是提醒你 DNS 只是一個(gè)應(yīng)用層協(xié)議。
運(yùn)輸層的任務(wù)就是將應(yīng)用層推出套接字的所有數(shù)據(jù)報(bào)收集起來,并且按照應(yīng)用層指定的運(yùn)輸層協(xié)議,TCP 或 UDP,重新封裝應(yīng)用層數(shù)據(jù)報(bào),并推給網(wǎng)絡(luò)層等待發(fā)送。
TCP 和 UDP 是運(yùn)輸層的兩個(gè)協(xié)議,前者是基于連接的可靠傳輸協(xié)議,后者是無連接的不可靠傳輸協(xié)議,所以前者更適合于一些對(duì)數(shù)據(jù)完整性要求高的場(chǎng)合,后者則適合于那種可以允許數(shù)據(jù)丟失但對(duì)傳輸速率要求特別高的場(chǎng)景,例如:語音電話,視頻等,丟一兩個(gè)包最多卡頓一下,無傷大雅。
UDP
UDP 不同于 TCP 那樣復(fù)雜,它既不保證數(shù)據(jù)可靠的傳輸?shù)侥康牡?,也不保證數(shù)據(jù)按序到達(dá)目的地,僅僅提供了簡單的差錯(cuò)檢驗(yàn)。報(bào)文格式如下:
其中,數(shù)據(jù)就是應(yīng)用層推出來的數(shù)據(jù),源端口號(hào)用于響應(yīng)報(bào)文的交付,目的端口號(hào)用于向目的進(jìn)程交付數(shù)據(jù),校驗(yàn)和用于檢查傳輸過程中數(shù)據(jù)是否受損,如果受損,UDP 將直接丟棄該報(bào)文。
TCP
TCP 要稍微復(fù)雜些,它是面向連接的,并且基于連接提供了可靠的數(shù)據(jù)傳輸服務(wù),它的數(shù)據(jù)報(bào)文格式如下:
單純的解釋報(bào)文格式中各個(gè)字段的含義并沒有太過實(shí)際的意義,你也很難理解了,在我們介紹 TCP 是如何『三次握手』,『四次揮手』以及『丟包重傳』等動(dòng)作時(shí),不間斷的會(huì)說明這些動(dòng)作時(shí)如何使用報(bào)文中的相關(guān)字段的。
首先我們來看耳熟能詳?shù)摹喝挝帐帧?,這基本上是 TCP 的代名詞了,無論懂不懂具體原理的人,提到 TCP,基本上都是知道『三次握手』的。
而本身,TCP 的三次握手就是為了確保通訊雙方能夠穩(wěn)定的建立連接并完成數(shù)據(jù)報(bào)文的請(qǐng)求與響應(yīng)動(dòng)作,至于為什么是三次握手而不是四次五次,這是一個(gè)哲學(xué)問題,這里就不做討論了。
第一步:
客戶端向服務(wù)端發(fā)送一份特殊的 TCP 報(bào)文,該報(bào)文并不包含應(yīng)用層的數(shù)據(jù),是一份特殊的報(bào)文,它的 TCP 首部中 SYN 字段值為 1 (參見上述報(bào)文格式)。
除此之外,客戶端還會(huì)隨機(jī)生成一個(gè)初始序號(hào),填在報(bào)文的「序號(hào)」字段,代表當(dāng)前報(bào)文的序號(hào)是這個(gè),并且我后續(xù)的分組會(huì)基于這個(gè)序號(hào)遞增。
然后該報(bào)文將會(huì)經(jīng)網(wǎng)絡(luò)層、鏈路層、物理層發(fā)送到服務(wù)端。
第二步:
如果分組丟失了,那么客戶端會(huì)經(jīng)過某個(gè)時(shí)間間隔再次嘗試發(fā)送。
而如果分組準(zhǔn)確的到達(dá)服務(wù)端了,服務(wù)端拆開 TCP 首部會(huì)看到,這是一個(gè)特殊的 SYN 握手報(bào)文,于是為此次連接分配緩存等資源。
接著服務(wù)端開始構(gòu)建響應(yīng)報(bào)文,SYN 是一個(gè)用于同步需要的字段,響應(yīng)報(bào)文中依然會(huì)被置為 1,并且服務(wù)端也將隨機(jī)生成一個(gè)初始序號(hào)放置的響應(yīng)報(bào)文的序號(hào)字段中。
最后,服務(wù)端還會(huì)為響應(yīng)報(bào)文中的確認(rèn)字段賦值,這個(gè)值就是客戶端發(fā)過來的那個(gè)序號(hào)值加一。
整體上的意思就是說,「我同意你的連接請(qǐng)求,我的初始序號(hào)為 xxx,你的初始序號(hào)我收到了,我等著你的下一個(gè)分組到來」
第三步:
客戶端收到服務(wù)端的響應(yīng)報(bào)文,于是分配客戶端 TCP 連接所必須的緩存等資源,于是連接已經(jīng)建立。
實(shí)際上從第三步開始,客戶端就可以攜帶應(yīng)用層數(shù)據(jù)向服務(wù)端交換報(bào)文了,以后的每份報(bào)文中,SYN 都為 0,因?yàn)樗皇怯糜谕匠跏夹蛱?hào)的,這一點(diǎn)需要明確。
總的來說,整個(gè)『握手』過程大致如下圖所示:
下面我們看看拆除一條 TCP 連接的『四次揮手』是怎樣的過程。
因?yàn)橐粭l TCP 連接會(huì)消耗大量的主機(jī)資源,不僅僅服務(wù)端需要分配各種緩存資源,客戶端也同樣需要分配相應(yīng)資源。因?yàn)?TCP 是『全雙工通信』,服務(wù)端和客戶端兩方其實(shí)是一樣的,誰是客戶誰是服務(wù)器是相對(duì)的。
強(qiáng)調(diào)這一點(diǎn)是為了說明,一條 TCP 連接不是只有客戶端才能斷開,服務(wù)端也同樣可以主動(dòng)斷開連接,這一點(diǎn)需要清楚。
我們這里假設(shè)客戶端主動(dòng)發(fā)起斷開連接的請(qǐng)求為例:
第一步:
客戶端構(gòu)建一份特殊的 TCP 報(bào)文,該報(bào)文首部字段 FIN 被置為 1,然后發(fā)送該報(bào)文。
第二步:
服務(wù)端收到該特殊的 FIN 報(bào)文,于是響應(yīng)客戶端一個(gè) ACK 報(bào)文,告訴客戶端,請(qǐng)求關(guān)閉的報(bào)文已經(jīng)收到,我正在處理。
第三步:
服務(wù)端發(fā)送一個(gè) FIN 報(bào)文,告訴客戶端,我將要關(guān)閉連接了。
第四步:
客戶端返回一個(gè) ACK 響應(yīng)報(bào)文,告訴服務(wù)端,我收到你剛才發(fā)的報(bào)文了,我已經(jīng)確認(rèn),你可以關(guān)閉連接了。
當(dāng)服務(wù)端收到客戶端發(fā)送的 ACK 響應(yīng)報(bào)文時(shí),將釋放服務(wù)端用于該 TCP 連接的所有資源,與此同時(shí),客戶端也會(huì)定時(shí)等待一定時(shí)間后完全釋放自己用于該連接的相關(guān)資源。
用一張圖更直觀的描述一下:
結(jié)合著圖與相關(guān)序號(hào)信息,我們?cè)僭敿?xì)說說其中的一些細(xì)節(jié)。
首先,客戶端發(fā)送一個(gè)特殊分組,該分組的序號(hào)為 u。發(fā)送完成之后,客戶端進(jìn)入 FIN-WAIT-1 這個(gè)狀態(tài),這個(gè)狀態(tài)下,該 TCP 連接的客戶端不再能發(fā)送數(shù)據(jù)報(bào),但是是可以接受數(shù)據(jù)報(bào)的,它等待著服務(wù)端的響應(yīng)報(bào)文。
接著,服務(wù)端收到客戶端發(fā)送的終止連接報(bào)文請(qǐng)求,服務(wù)端構(gòu)建響應(yīng)報(bào)文,告訴客戶端「序號(hào) u 1 以前的分組我都收到了」,并且進(jìn)入 CLOSE-WAIT 狀態(tài),這個(gè)狀態(tài)持續(xù)時(shí)間很短。
服務(wù)端會(huì)緊接著發(fā)送它的 FIN 數(shù)據(jù)報(bào),通知客戶端我服務(wù)端即將關(guān)閉連接,并隨即進(jìn)入 LAST_ACK 狀態(tài)等待客戶端響應(yīng)報(bào)文。
一旦客戶端收到這個(gè) FIN 報(bào)文,將返回確認(rèn)報(bào)文并進(jìn)入 TIME-WAIT 狀態(tài),等待 2MSL 時(shí)間間隔后完全釋放客戶端 TCP 連接所占用資源。
與此同時(shí),當(dāng)服務(wù)端收到客戶端最后的確認(rèn)報(bào)文,就將直接斷開服務(wù)端連接并釋放相關(guān)資源。
至于為什么最后客戶端需要等 2MSL 時(shí)間長度再完全釋放 TCP 相關(guān)資源呢?
那是因?yàn)?2MSL 是一份報(bào)文存在于網(wǎng)絡(luò)中最長的時(shí)間,超過該時(shí)間到達(dá)的報(bào)文都將被丟棄,而如果客戶端最后的確認(rèn)報(bào)文于網(wǎng)絡(luò)中丟失的話,服務(wù)端必將發(fā)起超時(shí)請(qǐng)求,重新發(fā)送第三次揮手動(dòng)作,此時(shí)等待中的客戶端就可隨即重新發(fā)送一份確認(rèn)請(qǐng)求。
這是為什么客戶端等待一個(gè)最長報(bào)文傳輸時(shí)間的原因。有人可能好奇為什么前面的各次請(qǐng)求都沒有做超時(shí)等待而只最后一次數(shù)據(jù)發(fā)送做了超時(shí)等待?
其實(shí)原因很簡單,相信你也能想到,就是 TCP 自帶計(jì)時(shí)能力,超過一定時(shí)間沒有收到某個(gè)報(bào)文的確認(rèn)報(bào)文,會(huì)自動(dòng)重新發(fā)送,而這里如果不做等待而直接關(guān)閉連接,那么我如何知道服務(wù)端到底收到?jīng)]我的確認(rèn)報(bào)文呢。
通過等待一個(gè)最長周期,如果這個(gè)周期內(nèi)沒有收到服務(wù)端的報(bào)文請(qǐng)求,那么我們的確認(rèn)報(bào)文必然是到達(dá)了服務(wù)端了的,否則重復(fù)發(fā)送一次即可。
至此,TCP 的『三次握手』和『四次揮手』我們已經(jīng)簡單描述完成了,下面我們看看 TCP 的一些其他特性,比如:可靠傳輸,擁塞控制等
首先我們來看 TCP 是如何實(shí)現(xiàn)可靠傳輸?shù)?,即如何解決網(wǎng)絡(luò)傳輸中丟包的問題。
TCP 使用『回退 N 步』協(xié)議實(shí)現(xiàn)的可靠傳輸,準(zhǔn)確來說,TCP 是在它的基礎(chǔ)上進(jìn)行了一部分優(yōu)化。
『回退 N 步』協(xié)議也被稱作『滑動(dòng)窗口』協(xié)議,即最多允許發(fā)送方有 N 個(gè)「已發(fā)送但未被確認(rèn)」的數(shù)據(jù)報(bào)文,如圖所示,p1 到 p3 長度即為 N,這里的窗口指的就是 p1 到 p3 這個(gè)區(qū)間。
只有當(dāng)發(fā)送端收到 p1 的確認(rèn)報(bào)文后,整個(gè)窗口才能向前滑動(dòng),而實(shí)際上在沒有收到 p1 的確認(rèn)報(bào)文前,即便它后面的報(bào)文已經(jīng)被接收,服務(wù)端也僅僅會(huì)緩存這些『非預(yù)期的報(bào)文』
直到服務(wù)端收到最小預(yù)期的那個(gè)報(bào)文后,從緩存中取出已經(jīng)到達(dá)的后續(xù)報(bào)文,合并并向上交付,然后向發(fā)送端返回一個(gè)確認(rèn)報(bào)文。
當(dāng)發(fā)送端窗口從左往右已經(jīng)連續(xù)多個(gè)報(bào)文被確認(rèn)后,整個(gè)窗口將向前滑動(dòng)多個(gè)單位長度。
下面我們看一個(gè)例子:
這是一個(gè)發(fā)送方的窗口,灰色表示已經(jīng)被確認(rèn)的報(bào)文,黃色表示已發(fā)送但未被確認(rèn)的報(bào)文,綠色表示下一個(gè)待發(fā)送的報(bào)文,白色表示不可用的報(bào)文。
這是我們假設(shè)服務(wù)端已經(jīng)收到 6、7 兩份報(bào)文,但是它上一次向上交付給應(yīng)用層的是 4 號(hào)報(bào)文,也就是說它在等 5 號(hào)報(bào)文,所以它暫時(shí)會(huì)將 6、7 兩個(gè)報(bào)文緩存起來,等到 5 號(hào)報(bào)文來了一并交付給應(yīng)用層。
現(xiàn)在 5 號(hào)報(bào)文由于超時(shí)被重傳了,終于到達(dá)目的地了,如愿以償,服務(wù)端向上交付 5、6、7 三份報(bào)文,并返回一份確認(rèn)報(bào)文,ACK = 8,表示序號(hào) 8 以前的所有報(bào)文都收到了。
當(dāng)發(fā)送端收到這份確認(rèn)報(bào)文后,5、6、7 變成灰色,窗口向前移動(dòng)三個(gè)單位長度。
此外,我還想強(qiáng)調(diào)一個(gè)細(xì)節(jié),TCP 是沒有否定確認(rèn)的,所以如果服務(wù)端連續(xù)響應(yīng)的多份報(bào)文是對(duì)同一序號(hào)的確認(rèn),那很有可能該序號(hào)以后的某個(gè)報(bào)文丟失。
例如:如果服務(wù)端發(fā)送多個(gè)對(duì)分組 5 的 ACK 確認(rèn),那說明什么?說明目前我服務(wù)端完整的向上交付的序號(hào)是 5 號(hào),后續(xù)的報(bào)文我沒收到,你最好重新發(fā)一下別等待超時(shí)了。
這也是『快速重傳』的核心原理。
那么 TCP 的可靠傳輸我們也基本介紹完了,下面我們看看如果網(wǎng)絡(luò)擁塞的時(shí)候,TCP 是如何控制發(fā)送流量的呢?
TCP 認(rèn)為:丟包即擁塞,需要降低發(fā)送效率,而每一次收到確認(rèn)數(shù)據(jù)報(bào)即認(rèn)為網(wǎng)絡(luò)通暢,會(huì)增加發(fā)送效率。
TCP 的擁塞控制算法包含三個(gè)部分,慢啟動(dòng)、擁塞避免和快速恢復(fù)。
慢啟動(dòng)的思想是,剛開始緩慢的發(fā)送,比如某個(gè)時(shí)間段內(nèi)只發(fā)送一次數(shù)據(jù)報(bào),當(dāng)收到確認(rèn)報(bào)文后,下一次同樣的時(shí)間間隔內(nèi),將發(fā)送兩倍速率的兩份數(shù)據(jù)報(bào),并以此類推。
所以,短時(shí)間內(nèi),一個(gè) TCP 連接的發(fā)送方將以指數(shù)級(jí)增長,但一旦出現(xiàn)丟包,即收到冗余的 ACK 確認(rèn),或者對(duì)于一個(gè)包的確認(rèn) ACK 始終沒收到而不得不啟動(dòng)一次超時(shí)重傳,那么發(fā)送方認(rèn)為「網(wǎng)絡(luò)是擁塞的」。
于是將速率直接調(diào)成一,即一個(gè)往返時(shí)間段,只發(fā)送一個(gè)分組,并且設(shè)置一個(gè)變量 ssthresh 表述一個(gè)閾值的概念,這個(gè)值是上次丟包時(shí)發(fā)送方發(fā)送速率的一半。
之后的發(fā)送方的發(fā)送效率一樣會(huì)以指數(shù)級(jí)增長,但是不同于第一次,這次一旦達(dá)到這個(gè)閾值,TCP 將進(jìn)入『擁塞避免』模式,該模式下的發(fā)送效率將不再指數(shù)級(jí)增長,會(huì)謹(jǐn)慎的增長。
擁塞避免的思想是,每個(gè)往返時(shí)間段發(fā)送的所有數(shù)據(jù)報(bào)全部得到確認(rèn)后,下一次就增加一個(gè)分組的發(fā)送,這樣緩慢的增長效率是謹(jǐn)慎的。
那么一旦出現(xiàn)發(fā)送端超時(shí)丟包,注意這里是超時(shí),將發(fā)送速率置為一并重新進(jìn)入慢啟動(dòng)狀態(tài),閾值就是當(dāng)前發(fā)送效率的一半。
而如果是服務(wù)端返回多個(gè)冗余 ACK 以明確你丟包,TCP 認(rèn)為這不是嚴(yán)重的,對(duì)于這種情況,TCP 減半當(dāng)前發(fā)送效率并進(jìn)入快速恢復(fù)階段。
快速恢復(fù)的基本思想是,收到幾個(gè)冗余的 ACK 就增加幾個(gè)分組的發(fā)送效率,就是說,你服務(wù)端不是沒收到我的幾個(gè)報(bào)文嗎,這兩次發(fā)送我提升速率迅速發(fā)給你。
當(dāng)這期間出現(xiàn)了由發(fā)送端超時(shí)導(dǎo)致的丟包,同樣的處理方式,初始化發(fā)送速率為一并減半當(dāng)前發(fā)送效率作為閾值,進(jìn)入慢啟動(dòng)階段。
當(dāng)然,如果這期間收到了對(duì)丟失報(bào)文的確認(rèn),那么將適當(dāng)降低發(fā)送效率并進(jìn)入擁塞避免狀態(tài)。
這樣,整個(gè) TCP 最核心的幾個(gè)思想都已經(jīng)介紹完了,整個(gè)運(yùn)輸層基本上也算明了了。關(guān)于運(yùn)輸層,你應(yīng)當(dāng)有了一定的理解,我再總結(jié)一下。
運(yùn)輸層的任務(wù)就是從應(yīng)用層的各個(gè)進(jìn)程的套接字那取回來所有需要發(fā)送的數(shù)據(jù),然后選擇 TCP 或者 UDP 將數(shù)據(jù)封裝并推給下面的網(wǎng)絡(luò)層待發(fā)送。
未完,待續(xù)。。。
聯(lián)系客服