【網(wǎng)絡(luò)是怎樣連接的】第2章 - 用電信號(hào)傳輸 TCP/IP 數(shù)據(jù)(3)

2.3 收發(fā)數(shù)據(jù)

將HTTP請(qǐng)求消息交給協(xié)議棧

當(dāng)控制流程從connect回到應(yīng)用程序之后,接下來(lái)就進(jìn)入數(shù)據(jù)收發(fā)階段了弹沽。

  • 首先窜锯,協(xié)議棧并不關(guān)心應(yīng)用程序傳來(lái)的數(shù)據(jù)是什么內(nèi)容熏挎。應(yīng)用程序在調(diào)用write時(shí)會(huì)指定發(fā)送數(shù)據(jù)的長(zhǎng)度蚌成,在協(xié)議椙岸唬看來(lái),要發(fā)送的數(shù)據(jù)就是一定長(zhǎng)度的二進(jìn)制字節(jié)序列而已担忧。

  • 其次芹缔,協(xié)議棧并不是一收到數(shù)據(jù)就馬上發(fā)送出去,而是會(huì)將數(shù)據(jù)存放在內(nèi)部的發(fā)送緩沖區(qū)中瓶盛,并等待應(yīng)用程序的下一段數(shù)據(jù)最欠。這樣做是有道理的。應(yīng)用程序交給協(xié)議棧發(fā)送的數(shù)據(jù)長(zhǎng)度是由應(yīng)用程序本身來(lái)決定的惩猫,不同的應(yīng)用程序在實(shí)現(xiàn)上有所不同芝硬,有些程序會(huì)一次性傳遞所有的數(shù)據(jù),有些程序則會(huì)逐字節(jié)或者逐行傳遞數(shù)據(jù)轧房“枰酰總之,一次將多少數(shù)據(jù)交給協(xié)議棧是由應(yīng)用程序自行決定的锯厢,協(xié)議棧并不能控制這一行為皮官。

第一個(gè)判斷要素是每個(gè)網(wǎng)絡(luò)包能容納的數(shù)據(jù)長(zhǎng)度脯倒,協(xié)議棧會(huì)根據(jù)一個(gè)叫作MTU的參數(shù)來(lái)進(jìn)行判斷实辑。
另一個(gè)判斷要素是時(shí)間捺氢。

MTU:一個(gè)網(wǎng)絡(luò)包的最大長(zhǎng)度,以太網(wǎng)中一般為1500字節(jié)剪撬。
MSS:除去頭部之后摄乒,一個(gè)網(wǎng)絡(luò)包所能容納的TCP數(shù)據(jù)的最大長(zhǎng)度。

圖2.5 MTU與MSS.png

協(xié)議棧發(fā)送數(shù)據(jù)的判斷要素:第一個(gè)判斷要素是每個(gè)網(wǎng)絡(luò)包能容納的數(shù)據(jù)長(zhǎng)度残黑,協(xié)議棧會(huì)根據(jù)一個(gè)叫作MTU的參數(shù)來(lái)進(jìn)行判斷馍佑。另一個(gè)判斷要素是時(shí)間。

在進(jìn)行發(fā)送操作時(shí)需要綜合考慮這兩個(gè)要素以達(dá)到平衡梨水。不過拭荤,TCP協(xié)議規(guī)格中并沒有告訴我們?cè)鯓硬拍芷胶猓虼藢?shí)際如何判斷是由協(xié)議棧的開發(fā)者來(lái)決定的疫诽,也正是由于這個(gè)原因舅世,不同種類和版本的操作系統(tǒng)在相關(guān)操作上也就存在差異。

協(xié)議棧也給應(yīng)用程序保留了控制發(fā)送時(shí)機(jī)的余地奇徒。應(yīng)用程序在發(fā)送數(shù)據(jù)時(shí)可以指定一些選項(xiàng)雏亚,比如如果指定“不等待填滿緩沖區(qū)直接發(fā)送”,則協(xié)議棧就會(huì)按照要求直接發(fā)送數(shù)據(jù)摩钙。像瀏覽器這種會(huì)話型的應(yīng)用程序在向服務(wù)器發(fā)送數(shù)據(jù)時(shí)罢低,等待填滿緩沖區(qū)導(dǎo)致延遲會(huì)產(chǎn)生很大影響,因此一般會(huì)使用直接發(fā)送的選項(xiàng)胖笛。

對(duì)較大的數(shù)據(jù)進(jìn)行拆分

圖2.6 應(yīng)用程序數(shù)據(jù)的拆分發(fā)送.png

根據(jù)發(fā)送緩沖區(qū)中的數(shù)據(jù)拆分的情況网持,當(dāng)判斷需要發(fā)送這些數(shù)據(jù)時(shí),就在每一塊數(shù)據(jù)前面加上TCP頭部长踊,并根據(jù)套接字中記錄的控制信息標(biāo)記發(fā)送方和接收方的端口號(hào)功舀,然后交給IP模塊來(lái)執(zhí)行發(fā)送數(shù)據(jù)的操作(圖2.6)。

使用ACK號(hào)確認(rèn)網(wǎng)絡(luò)包已收到

  • 首先之斯,TCP模塊在拆分?jǐn)?shù)據(jù)時(shí)日杈,會(huì)先算好每一塊數(shù)據(jù)相當(dāng)于從頭開始的第幾個(gè)字節(jié),接下來(lái)在發(fā)送這一塊數(shù)據(jù)時(shí)佑刷,將算好的字節(jié)數(shù)寫在TCP頭部中莉擒,“序號(hào)”字段就是派在這個(gè)用場(chǎng)上的。

  • 然后瘫絮,發(fā)送數(shù)據(jù)的長(zhǎng)度也需要告知接收方涨冀,不過這個(gè)并不是放在TCP頭部里面的,因?yàn)橛谜麄€(gè)網(wǎng)絡(luò)包的長(zhǎng)度減去頭部的長(zhǎng)度就可以得到數(shù)據(jù)的長(zhǎng)度麦萤,所以接收方可以用這種方法來(lái)進(jìn)行計(jì)算鹿鳖。

有了上面兩個(gè)數(shù)值扁眯,我們就可以知道發(fā)送的數(shù)據(jù)是從第幾個(gè)字節(jié)開始,長(zhǎng)度是多少了翅帜。
通過這些信息姻檀,接收方還能夠檢查收到的網(wǎng)絡(luò)包有沒有遺漏。

在實(shí)際的通信中涝滴,序號(hào)并不是從1開始的绣版,而是需要用隨機(jī)數(shù)計(jì)算出一個(gè)初始值,這是因?yàn)槿绻蛱?hào)都從1開始歼疮,通信過程就會(huì)非常容易預(yù)測(cè)杂抽,有人會(huì)利用這一點(diǎn)來(lái)發(fā)動(dòng)攻擊。但是如果初始值是隨機(jī)的韩脏,那么對(duì)方就搞不清楚序號(hào)到底是從多少開始計(jì)算的缩麸,因此需要在開始收發(fā)數(shù)據(jù)之前將初始值告知通信對(duì)象。大家應(yīng)該還記得在我們剛才講過的連接過程中赡矢,有一個(gè)將SYN控制位設(shè)為1并發(fā)送給服務(wù)器的操作杭朱,就是在這一步將序號(hào)的初始值告知對(duì)方的。實(shí)際上济竹,在將SYN設(shè)為1的同時(shí)痕檬,還需要同時(shí)設(shè)置序號(hào)字段的值,而這里的值就代表序號(hào)的初始值送浊。

通過“序號(hào)”和“ACK號(hào)”可以確認(rèn)接收方是否收到了網(wǎng)絡(luò)包梦谜。

網(wǎng)卡、集線器袭景、路由器都沒有錯(cuò)誤補(bǔ)償機(jī)制唁桩,一旦檢測(cè)到錯(cuò)誤就直接丟棄相應(yīng)的包。應(yīng)用程序也是一樣耸棒,因?yàn)椴捎肨CP傳輸荒澡,即便發(fā)生一些錯(cuò)誤對(duì)方最終也能夠收到正確的數(shù)據(jù),所以應(yīng)用程序只管自顧自地發(fā)送這些數(shù)據(jù)就好了与殃。

根據(jù)網(wǎng)絡(luò)包平均往返時(shí)間調(diào)整ACK號(hào)等待時(shí)間

在公司里的局域網(wǎng)環(huán)境下单山,幾毫秒就可以返回ACK號(hào),但在互聯(lián)網(wǎng)環(huán)境中幅疼,當(dāng)遇到擁塞時(shí)需要幾百毫秒才能返回ACK號(hào)也并不稀奇米奸。
正因?yàn)椴▌?dòng)如此之大,所以將等待時(shí)間設(shè)置為一個(gè)固定值并不是一個(gè)好辦法爽篷。因此悴晰,TCP采用了動(dòng)態(tài)調(diào)整等待時(shí)間的方法,這個(gè)等待時(shí)間是根據(jù)ACK號(hào)返回所需的時(shí)間來(lái)判斷的。

TCP會(huì)在發(fā)送數(shù)據(jù)的過程中持續(xù)測(cè)量ACK號(hào)的返回時(shí)間铡溪,如果ACK號(hào)返回變慢漂辐,則相應(yīng)延長(zhǎng)等待時(shí)間;相對(duì)地棕硫,如果ACK號(hào)馬上就能返回髓涯,則相應(yīng)縮短等待時(shí)間。

圖2.7 序號(hào)和ack號(hào)的用法.png

使用窗口有效管理ACK號(hào)

滑動(dòng)窗口饲帅,就是在發(fā)送一個(gè)包之后复凳,不等待ACK號(hào)返回瘤泪,而是直接發(fā)送后續(xù)的一系列包灶泵。這樣一來(lái),等待ACK號(hào)的這段時(shí)間就被有效利用起來(lái)了对途。

接收方需要告訴發(fā)送方自己最多能接收多少數(shù)據(jù)赦邻,然后發(fā)送方根據(jù)這個(gè)值對(duì)數(shù)據(jù)發(fā)送操作進(jìn)行控制,這就是滑動(dòng)窗口方式的基本思路实檀。

當(dāng)接收方的TCP收到包后惶洲,會(huì)先將數(shù)據(jù)存放到接收緩沖區(qū)中。然后膳犹,接收方需要計(jì)算ACK號(hào)恬吕,將數(shù)據(jù)塊組裝起來(lái)還原成原本的數(shù)據(jù)并傳遞給應(yīng)用程序,如果這些操作還沒完成下一個(gè)包就到了也不用擔(dān)心须床,因?yàn)橄乱粋€(gè)包也會(huì)被暫存在接收緩沖區(qū)中铐料。如果數(shù)據(jù)到達(dá)的速率比處理這些數(shù)據(jù)并傳遞給應(yīng)用程序的速率還要快,那么接收緩沖區(qū)中的數(shù)據(jù)就會(huì)越堆越多豺旬,最后就會(huì)溢出钠惩。緩沖區(qū)溢出之后,后面的數(shù)據(jù)就進(jìn)不來(lái)了族阅,因此接收方就收不到后面的包了篓跛,這就和中途出錯(cuò)的結(jié)果是一樣的,也就意味著超出了接收方處理能力坦刀。我們可以通過下面的方法來(lái)避免這種情況的發(fā)生愧沟。

接收方需要告訴發(fā)送方自己最多能接收多少數(shù)據(jù),然后發(fā)送方根據(jù)這個(gè)值對(duì)數(shù)據(jù)發(fā)送操作進(jìn)行控制鲤遥,這就是滑動(dòng)窗口方式的基本思路沐寺。

前面提到的能夠接收的最大數(shù)據(jù)量稱為窗口大小,它是TCP調(diào)優(yōu)參數(shù)中非常有名的一個(gè)渴频。


圖2.10 一來(lái)一回方式和滑動(dòng)窗口方式.png

ACK與窗口的合并

更新窗口大小的時(shí)機(jī)應(yīng)該是接收方從緩沖區(qū)中取出數(shù)據(jù)傳遞給應(yīng)用程序的時(shí)候芽丹。這個(gè)操作是接收方應(yīng)用程序發(fā)出請(qǐng)求時(shí)才會(huì)進(jìn)行的,而發(fā)送方不知道什么時(shí)候會(huì)進(jìn)行這樣的操作卜朗,因此當(dāng)接收方將數(shù)據(jù)傳遞給應(yīng)用程序拔第,導(dǎo)致接收緩沖區(qū)剩余容量增加時(shí)咕村,就需要告知發(fā)送方,這就是更新窗口大小的時(shí)機(jī)蚊俺。

那么ACK號(hào)又是什么情況呢懈涛?當(dāng)接收方收到數(shù)據(jù)時(shí),如果確認(rèn)內(nèi)容沒有問題泳猬,就應(yīng)該向發(fā)送方返回ACK號(hào)批钠,因此我們可以認(rèn)為收到數(shù)據(jù)之后馬上就應(yīng)該進(jìn)行這一操作。

  • 發(fā)送方的數(shù)據(jù)到達(dá)接收方得封,在接收操作完成之后就需要向發(fā)送方返回ACK號(hào)埋心,而再經(jīng)過一段時(shí)間,當(dāng)數(shù)據(jù)傳遞給應(yīng)用程序之后才需要更新窗口大小忙上。但如果根據(jù)這樣的設(shè)計(jì)來(lái)實(shí)現(xiàn)拷呆,每收到一個(gè)包,就需要向發(fā)送方分別發(fā)送ACK號(hào)和窗口更新這兩個(gè)單獨(dú)的包疫粥。這樣一來(lái)茬斧,接收方發(fā)給發(fā)送方的包就太多了,導(dǎo)致網(wǎng)絡(luò)效率下降梗逮。

  • 在等待發(fā)送ACK號(hào)的時(shí)候正好需要更新窗口项秉,這時(shí)就可以把ACK號(hào)和窗口更新放在一個(gè)包里發(fā)送,從而減少包的數(shù)量慷彤。當(dāng)需要連續(xù)發(fā)送多個(gè)ACK號(hào)時(shí)娄蔼,也可以減少包的數(shù)量,這是因?yàn)锳CK號(hào)表示的是已收到的數(shù)據(jù)量瞬欧,也就是說贷屎,它是告訴發(fā)送方目前已接收的數(shù)據(jù)的最后位置在哪里,因此當(dāng)需要連續(xù)發(fā)送ACK號(hào)時(shí)艘虎,只要發(fā)送最后一個(gè)ACK號(hào)就可以了唉侄,中間的可以全部省略。當(dāng)需要連續(xù)發(fā)送多個(gè)窗口更新時(shí)也可以減少包的數(shù)量野建,因?yàn)檫B續(xù)發(fā)生窗口更新說明應(yīng)用程序連續(xù)請(qǐng)求了數(shù)據(jù)属划,接收緩沖區(qū)的剩余空間連續(xù)增加。這種情況和ACK號(hào)一樣候生,可以省略中間過程同眯,只要發(fā)送最終的結(jié)果就可以了。

接收HTTP響應(yīng)消息

首先唯鸭,瀏覽器在委托協(xié)議棧發(fā)送請(qǐng)求消息之后须蜗,會(huì)調(diào)用read程序(之前的圖2.3④)來(lái)獲取響應(yīng)消息。然后,控制流程會(huì)通過read轉(zhuǎn)移到協(xié)議棧明肮,然后協(xié)議棧會(huì)執(zhí)行接下來(lái)的操作菱农。和發(fā)送數(shù)據(jù)一樣,接收數(shù)據(jù)也需要將數(shù)據(jù)暫存到接收緩沖區(qū)中柿估,這里的操作過程如下循未。首先,協(xié)議棧嘗試從接收緩沖區(qū)中取出數(shù)據(jù)并傳遞給應(yīng)用程序秫舌,但這個(gè)時(shí)候請(qǐng)求消息剛剛發(fā)送出去的妖,響應(yīng)消息可能還沒返回。響應(yīng)消息的返回還需要等待一段時(shí)間足陨,因此這時(shí)接收緩沖區(qū)中并沒有數(shù)據(jù)嫂粟,那么接收數(shù)據(jù)的操作也就無(wú)法繼續(xù)。這時(shí)钠右,協(xié)議棧會(huì)將應(yīng)用程序的委托赋元,也就是從接收緩沖區(qū)中取出數(shù)據(jù)并傳遞給應(yīng)用程序的工作暫時(shí)掛起,等服務(wù)器返回的響應(yīng)消息到達(dá)之后再繼續(xù)執(zhí)行接收操作飒房。

大家可以認(rèn)為這時(shí)協(xié)議棧會(huì)進(jìn)入暫停狀態(tài),但實(shí)際上并非如此媚值。協(xié)議棧會(huì)負(fù)責(zé)處理來(lái)自很多應(yīng)用程序的工作狠毯,因此掛起其中一項(xiàng)工作并不意味著協(xié)議棧就完全暫停了,協(xié)議棧會(huì)繼續(xù)執(zhí)行其他的工作褥芒。在執(zhí)行其他工作的時(shí)候嚼松,掛起的工作并沒有在執(zhí)行,因此看上去和暫停是一樣的锰扶。

  • 首先献酗,協(xié)議棧會(huì)檢查收到的數(shù)據(jù)塊和TCP頭部的內(nèi)容,判斷是否有數(shù)據(jù)丟失坷牛,如果沒有問題則返回ACK號(hào)罕偎。

  • 然后,協(xié)議棧將數(shù)據(jù)塊暫存到接收緩沖區(qū)中京闰,并將數(shù)據(jù)塊按順序連接起來(lái)還原出原始的數(shù)據(jù)

  • 最后將數(shù)據(jù)交給應(yīng)用程序颜及。

具體來(lái)說,協(xié)議棧會(huì)將接收到的數(shù)據(jù)復(fù)制到應(yīng)用程序指定的內(nèi)存地址中蹂楣,然后將控制流程交回應(yīng)用程序俏站。將數(shù)據(jù)交給應(yīng)用程序之后,協(xié)議棧還需要找到合適的時(shí)機(jī)向發(fā)送方發(fā)送窗口更新痊土。


從支付寶轉(zhuǎn)賬功能新變化肄扎,看支付寶和微信支付轉(zhuǎn)賬差異

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子犯祠,更是在濱河造成了極大的恐慌萌丈,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,376評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件雷则,死亡現(xiàn)場(chǎng)離奇詭異辆雾,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)月劈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門度迂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人猜揪,你說我怎么就攤上這事惭墓。” “怎么了而姐?”我有些...
    開封第一講書人閱讀 156,966評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵腊凶,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我拴念,道長(zhǎng)钧萍,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,432評(píng)論 1 283
  • 正文 為了忘掉前任政鼠,我火速辦了婚禮风瘦,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘公般。我一直安慰自己万搔,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,519評(píng)論 6 385
  • 文/花漫 我一把揭開白布官帘。 她就那樣靜靜地躺著瞬雹,像睡著了一般。 火紅的嫁衣襯著肌膚如雪刽虹。 梳的紋絲不亂的頭發(fā)上酗捌,一...
    開封第一講書人閱讀 49,792評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音状婶,去河邊找鬼意敛。 笑死,一個(gè)胖子當(dāng)著我的面吹牛膛虫,可吹牛的內(nèi)容都是我干的草姻。 我是一名探鬼主播,決...
    沈念sama閱讀 38,933評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼稍刀,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼撩独!你這毒婦竟也來(lái)了敞曹?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,701評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤综膀,失蹤者是張志新(化名)和其女友劉穎澳迫,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體剧劝,經(jīng)...
    沈念sama閱讀 44,143評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡橄登,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,488評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了讥此。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拢锹。...
    茶點(diǎn)故事閱讀 38,626評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖萄喳,靈堂內(nèi)的尸體忽然破棺而出卒稳,到底是詐尸還是另有隱情,我是刑警寧澤他巨,帶...
    沈念sama閱讀 34,292評(píng)論 4 329
  • 正文 年R本政府宣布充坑,位于F島的核電站,受9級(jí)特大地震影響染突,放射性物質(zhì)發(fā)生泄漏捻爷。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,896評(píng)論 3 313
  • 文/蒙蒙 一觉痛、第九天 我趴在偏房一處隱蔽的房頂上張望役衡。 院中可真熱鬧,春花似錦薪棒、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至钉鸯,卻和暖如春吧史,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背唠雕。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工贸营, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人岩睁。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓钞脂,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親捕儒。 傳聞我的和親對(duì)象是個(gè)殘疾皇子冰啃,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,494評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容