TCP協(xié)議詳解——看完面試不愁

TCP\IP協(xié)議詳解

本文中用到的圖片轉(zhuǎn)自: 頭條文章

TCP與UDP協(xié)議有什么區(qū)別?

TCP是一個面向連接的、可靠的椎组、基于字節(jié)流的傳輸層協(xié)議父叙。

UDP是一個面向無連接的傳輸層協(xié)議。

與UDP相比卦睹,TCP有以下特性:

  1. 面向連接。所謂的連接,指的是客戶端和服務(wù)器的連接跌前,在雙方互相通信之前,TCP 需要三次握手建立連接陡舅,而 UDP 沒有相應(yīng)建立連接的過程抵乓。

  2. 可靠性。TCP 使用了非常多機制的保證連接的可靠靶衍,這個可靠性體現(xiàn)在哪些方面呢灾炭?一個是有狀態(tài),另一個是可控制颅眶。

  3. 面向字節(jié)流蜈出。UDP 的數(shù)據(jù)傳輸是基于數(shù)據(jù)報的,這是因為僅僅只是繼承了 IP 層的特性涛酗,而 TCP 為了維護狀態(tài)铡原,將一個個 IP 包變成了字節(jié)流。

TCP 會精準記錄哪些數(shù)據(jù)發(fā)送了商叹,哪些數(shù)據(jù)被對方接收了燕刻,哪些沒有被接收到,而且保證數(shù)據(jù)包按序到達剖笙,不允許半點差錯卵洗。這是有狀態(tài)

當意識到丟包了或者網(wǎng)絡(luò)環(huán)境不佳弥咪,TCP 會根據(jù)具體情況調(diào)整自己的行為过蹂,控制自己的發(fā)送速度或者重發(fā)。這是可控制酪夷。

相應(yīng)的榴啸,UDP 就是無狀態(tài), 不可控的。

三次握手

在介紹三次握手時我們先來看看TCP的報文頭格式:

823435-20170323092941611-1541980584.png
  • 端口號:用來標識同一臺計算機的不同的應(yīng)用進程晚岭。

  • 源端口:源端口和IP地址的作用是標識報文的返回地址鸥印。

  • 目的端口:端口指明接收方計算機上的應(yīng)用程序接口勋功。(TCP報頭中的源端口號和目的端口號同IP數(shù)據(jù)報中的源IP與目的IP唯一確定一條TCP連接。)

  • 序號和確認號:是TCP可靠傳輸?shù)年P(guān)鍵部分库说。序號是本報文段發(fā)送的數(shù)據(jù)組的第一個字節(jié)的序號狂鞋。在TCP傳送的流中,每一個字節(jié)一個序號潜的。e.g.一個報文段的序號為300骚揍,此報文段數(shù)據(jù)部分共有100字節(jié),則下一個報文段的序號為400啰挪。所以序號確保了TCP傳輸?shù)挠行蛐孕挪弧4_認號,即ACK亡呵,指明下一個期待收到的字節(jié)序號抽活,表明該序號之前的所有數(shù)據(jù)已經(jīng)正確無誤的收到。確認號只有當ACK標志為1時才有效锰什。比如建立連接時下硕,SYN報文的ACK標志位為0。

  • 數(shù)據(jù)偏移/首部長度:4bits汁胆。由于首部可能含有可選項內(nèi)容梭姓,因此TCP報頭的長度是不確定的,報頭不包含任何可選字段則長度為20字節(jié)嫩码,4位首部長度字段所能表示的最大值為1111誉尖,轉(zhuǎn)化為10進制為15,15*32/8 = 60铸题,故報頭最大長度為60字節(jié)释牺。首部長度也叫數(shù)據(jù)偏移,是因為首部長度實際上指示了數(shù)據(jù)區(qū)在報文段中的起始偏移值回挽。

  • 保留:為將來定義新的用途保留,現(xiàn)在一般置0猩谊。

  • 控制位:URG ACK PSH RST SYN FIN千劈,共6個,每一個標志位表示一個控制功能牌捷。

    1. URG:緊急指針標志墙牌,為1時表示緊急指針有效,為0則忽略緊急指針暗甥。

    2. ACK:確認序號標志喜滨,為1時表示確認號有效,為0表示報文中不含確認信息撤防,忽略確認號字段虽风。

    3. PSH:push標志,為1表示是帶有push標志的數(shù)據(jù),指示接收方在接收到該報文段以后辜膝,應(yīng)盡快將這個報文段交給應(yīng)用程序无牵,而不是在緩沖區(qū)排隊。

    4. RST:重置連接標志厂抖,用于重置由于主機崩潰或其他原因而出現(xiàn)錯誤的連接茎毁。或者用于拒絕非法的報文段和拒絕連接請求忱辅。

    5. SYN:同步序號七蜘,用于建立連接過程,在連接請求中墙懂,SYN=1和ACK=0表示該數(shù)據(jù)段沒有使用捎帶的確認域橡卤,而連接應(yīng)答捎帶一個確認,即SYN=1和ACK=1垒在。

    6. FIN:finish標志蒜魄,用于釋放連接,為1時表示發(fā)送方已經(jīng)沒有數(shù)據(jù)發(fā)送了场躯,即關(guān)閉本方數(shù)據(jù)流谈为。

  • 窗口:滑動窗口大小,用來告知發(fā)送端接受端的緩存大小踢关,以此控制發(fā)送端發(fā)送數(shù)據(jù)的速率伞鲫,從而達到流量控制。窗口大小16bit签舞,因此窗口大小最大為65535秕脓。

  • 校驗和:奇偶校驗,此校驗和是對整個的 TCP 報文段儒搭,包括 TCP 頭部和 TCP 數(shù)據(jù)吠架,以 16 位字進行計算所得。由發(fā)送端計算和存儲搂鲫,并由接收端進行驗證傍药。

  • 緊急指針:只有當 URG 標志置 1 時緊急指針才有效。緊急指針是一個正的偏移量魂仍,和順序號字段中的值相加表示緊急數(shù)據(jù)最后一個字節(jié)的序號拐辽。 TCP 的緊急方式是發(fā)送端向另一端發(fā)送緊急數(shù)據(jù)的一種方式。

  • 選項和填充:最常見的可選字段是最長報文大小擦酌,又稱為MSS(Maximum Segment Size)俱诸,每個連接方通常都在通信的第一個報文段(為建立連接而設(shè)置SYN標志為1的那個段)中指明這個選項,它表示本端所能接受的最大報文段的長度赊舶。選項長度不一定是32位的整數(shù)倍睁搭,所以要加填充位赶诊,即在這個字段中加入額外的零,以保證TCP頭是32的整數(shù)倍介袜。

  • 數(shù)據(jù)部分: TCP 報文段中的數(shù)據(jù)部分是可選的甫何。在一個連接建立和一個連接終止時,雙方交換的報文段僅有 TCP 首部遇伞。如果一方?jīng)]有數(shù)據(jù)要發(fā)送辙喂,也使用沒有任何數(shù)據(jù)的首部來確認收到的數(shù)據(jù)。在處理超時的許多情況中鸠珠,也會發(fā)送不帶任何數(shù)據(jù)的報文段巍耗。

報頭格式介紹完了,接下來我們看看TCP的三次握手過程:

823435-20170323092953893-1865298744.png

過程描述:

  • 客戶端發(fā)起連接請求渐排,報頭中的SYN=1炬太,ACK=0,TCP規(guī)定SYN=1時不能攜帶數(shù)據(jù)驯耻,但要消耗一個序號,因此聲明自己的序號是 seq=x亲族。此時客戶端狀態(tài)CLOSED->SYN-SENT

  • 服務(wù)器接收到連接請求可缚,然后進行回復確認霎迫,發(fā)送SYN=1 ACK=1 seq=y ack=x+1。此時服務(wù)端狀態(tài)LISTEN->SYN-RCVD

  • 客戶端收到對SYN的確認包之后再次確認帘靡,SYN=0 ACK=1 seq=x+1 ack=y+1知给,此時客戶端狀態(tài)SYN-SENT->ESTABLISHED

  • 服務(wù)端接收到客戶端的確認包后狀態(tài)變?yōu)?strong>ESTABLISHED

    為什么要進行三次握手?

    保證通信是“全雙工”的描姚,即客戶端和服務(wù)器都具備發(fā)送和接收能力涩赢,假如沒有客戶端的第二次確認,那么服務(wù)端無法確毙保客戶端已經(jīng)接收到自己發(fā)出去的SYN確認包筒扒。而且假如只有兩次握手贬派,那么會存在資源浪費的情況:

    客戶端發(fā)出SYN請求后单鹿,由于網(wǎng)絡(luò)復雜情況,這個請求一直沒有發(fā)送到服務(wù)器端慢哈,這時候客戶端超時重發(fā)第二個請求榛斯,然后第二個請求服務(wù)端正常接收并建立連接,數(shù)據(jù)傳輸完畢后雙方斷開了連接搂捧,但這時候第一次發(fā)送的那個SYN包終于到達服務(wù)端了驮俗,由于是二次握手,所以服務(wù)端發(fā)送確認包允跑,并建立連接王凑,但是客戶端實際上已經(jīng)斷開連接了搪柑,而服務(wù)端建立了一條“沒有”客戶端的連接,造成了資源浪費索烹。

    重傳機制

    三次握手結(jié)束之后就可以開始收發(fā)數(shù)據(jù)了工碾,那要怎么保證我們發(fā)送出去的消息確實被接收到了呢?以寄快遞為例百姓,雖然我們寄快遞前確認收件人信息無誤渊额,但是快遞寄出去的時候,如果我們沒有收到反饋(比如收件人告知你快遞我已經(jīng)收到了或者是快遞公司的收件通知)垒拢。那么我們是無法知道快遞是否準確送達的旬迹。

    在TCP中,是通過序列號與確認應(yīng)答來保證的(回想下上面的報頭格式)求类。正常的傳輸過程如下:

6f12b7827bba411b8d20d8a8b5b50bba.png

但是實際情況是非常復雜的奔垦,假如網(wǎng)絡(luò)出現(xiàn)丟包的情況要怎么辦呢?這就涉及到TCP的重傳機制

  • 超時重傳
  • 快速重傳
  • SACK
  • D-SACK

超時重傳

在發(fā)送數(shù)據(jù)時尸疆,設(shè)定一個定時器椿猎,當超過指定的時間后,沒有收到對方的 ACK 確認應(yīng)答報文寿弱,就會重發(fā)該數(shù)據(jù)犯眠。

數(shù)據(jù)包丟失或者確認應(yīng)答丟失時會發(fā)生超時重傳:

1189ad86c82847d5a4d2a325312bfab4.png

問題來了,這個“特定的時間間隔”應(yīng)該設(shè)置成多少合適呢脖捻?這就引入了RTT(Round-Trip Time 往返時延)的概念:

cf10b4cef2284178942306dcd5ac17a8.png

RTT簡單來說就是數(shù)據(jù)一次往返的時間阔逼,超時重傳時間是以 RTO (Retransmission Timeout 超時重傳時間)表示。這個重傳時間的設(shè)置比較玄學地沮,設(shè)置高了或者低了都會有問題:

9a0a2e09eee245b8a2fdac908530fb96.png

其實不用看圖片大家應(yīng)該也能猜到嗜浮,超時時間過大,那么就會導致效率的降低(大部分時間都用來等待)摩疑。超時時間過低的話那就有可能造成不必要的重傳(重傳剛發(fā)出去結(jié)果就收到了應(yīng)答)危融。

所以RTO的計算方法比較復雜,因為網(wǎng)絡(luò)狀態(tài)是時時刻刻變化的雷袋,而且也會存在波動較大的情況吉殃,所以RTO的值也是動態(tài)變化的,這里面的算法就不贅述了~~~有興趣的小伙伴可以網(wǎng)上查找相關(guān)資料楷怒。

快速重傳

我們一直強調(diào)網(wǎng)絡(luò)情況是非常復雜的蛋勺,所以上面提到的超時重傳無法解決所有問題,設(shè)想這么一種場景:數(shù)據(jù)包只是因為某一個網(wǎng)絡(luò)節(jié)點的異常而丟失了鸠删,實際上網(wǎng)路是“暢通”的抱完,假如還是使用超時重傳那么效率顯然太低了,因此刃泡,快速重傳機制誕生了巧娱。

fd8888b8b0b440788f3c875d1ba4436c.png
  • 發(fā)送端發(fā)送了5份數(shù)據(jù)碉怔;
  • 接收方接收到seq1時返回ACK2,但是seq2由于網(wǎng)絡(luò)異常丟包沒有收到禁添;
  • 這時候接收端又接收到seq3撮胧,在應(yīng)答的時候依然返回ACK2;
  • 后續(xù)seq4和seq5也收到了老翘,但是seq2還沒有收到芹啥,依然返回ACK2。
  • 發(fā)送端連續(xù)收到三次同樣的ACK2酪捡,知道seq2沒有被接收到叁征,就會在定時器任務(wù)觸發(fā)之前重傳seq2。
  • 接收端接收到seq2逛薇,而且檢測到seq3捺疼、4、5都已經(jīng)收到永罚。所以返回ACK6

所以啤呼,快速重傳的工作方式是當收到三個相同的 ACK 報文時,會在定時器過期之前呢袱,重傳丟失的報文段官扣。

但是快速重傳也有問題,發(fā)送端只知道seq2丟失了惕蹄,但是不知道seq3、4卖陵、5有沒有被接收到。所以發(fā)送端并不清楚要不要把后續(xù)的seq3、4、5一并重傳。于是便引入了SACK

SACK( Selective Acknowledgment 選擇性確認)

這種方式需要在 TCP 頭部「選項」字段里加一個 SACK卿吐,他可以記錄已接收的數(shù)據(jù),隨著報頭一起發(fā)送給發(fā)送方锋华,這樣發(fā)送方就清楚什么數(shù)據(jù)被接收了嗡官,什么數(shù)據(jù)沒有接收,這樣就可以只重傳丟失的數(shù)據(jù)毯焕。

7135037248b348c2bf2d37e46750ff9d.png

發(fā)送方收到了三次同樣的 ACK 確認報文衍腥,于是就會觸發(fā)快速重發(fā)機制,通過SACK 信息發(fā)現(xiàn)只有 200~299 這段數(shù)據(jù)丟失纳猫,重發(fā)時只需要重傳這段數(shù)據(jù)即可婆咸。

如果要支持 SACK,必須雙方都要支持芜辕。在 Linux 下尚骄,可以通過 net.ipv4.tcp_sack參數(shù)打開這個功能(Linux 2.4 后默認打開)。

Duplicate SACK

Duplicate SACK 又稱 D-SACK侵续,其主要使用了 SACK 來告訴「發(fā)送方」有哪些數(shù)據(jù)被重復接收了倔丈。 主要解決下面兩種情況:

732bc94fd4714c95ae94262f15224d3e.png

ACK丟包。

ab58dca206e14b35a0fbed4d6799113e.png

網(wǎng)絡(luò)延時状蜗。

在 Linux 下可以通過 net.ipv4.tcp_dsack 參數(shù)開啟/關(guān)閉這個功能(Linux 2.4 后默認打開)需五。

滑動窗口

細心的小伙伴可能發(fā)現(xiàn)了,上面的圖片里面并不是等到上一次數(shù)據(jù)的確認收到之后才發(fā)送下一批數(shù)據(jù)轧坎,因為串行發(fā)送數(shù)據(jù)效率太低宏邮,所以TCP引入了滑動窗口的概念。

有了窗口缸血,就可以指定窗口大小蜜氨,窗口大小就是指無需等待確認應(yīng)答,而可以繼續(xù)發(fā)送數(shù)據(jù)的最大值属百。

窗口的實現(xiàn)實際上是操作系統(tǒng)開辟的一個緩存空間记劝,發(fā)送方主機在等到確認應(yīng)答返回之前,必須在緩沖區(qū)中保留已發(fā)送的數(shù)據(jù)族扰。如果按期收到確認應(yīng)答厌丑,此時數(shù)據(jù)就可以從緩存區(qū)清除。

假設(shè)窗口大小為 3 個 TCP 段渔呵,那么發(fā)送方就可以「連續(xù)發(fā)送」 3 個 TCP 段怒竿,并且中途若有 ACK 丟失,可以通過「下一個確認應(yīng)答進行確認」扩氢。如下圖:

04973b1e0f99426cad89c0e8a826c6ac.png

圖中的 ACK 600 確認應(yīng)答報文丟失耕驰,也沒關(guān)系,因為可以通過下一個確認應(yīng)答進行確認录豺,只要發(fā)送方收到了 ACK 700 確認應(yīng)答朦肘,就意味著 700 之前的所有數(shù)據(jù)「接收方」都收到了饭弓。這個模式就叫累計確認或者累計應(yīng)答

那么窗口大小應(yīng)該怎么設(shè)置呢媒抠?

回想一下TCP報頭格式弟断,是不是有一個“窗口”字段?這個“窗口”字段就是用來表示窗口大小的趴生。這個字段是接收端告訴發(fā)送端自己還有多少緩沖區(qū)可以接收數(shù)據(jù)阀趴。于是發(fā)送端就可以根據(jù)接收端的處理能力來發(fā)送數(shù)據(jù),而不會導致接收端處理不過來苍匆。

所以刘急,通常窗口的大小是由接收方的決定的。

發(fā)送方發(fā)送的數(shù)據(jù)大小不能超過接收方的窗口大小浸踩,否則接收方就無法正常接收到數(shù)據(jù)叔汁。

下圖就是發(fā)送方緩存的數(shù)據(jù),根據(jù)處理的情況分成四個部分民轴,其中深藍色方框是發(fā)送窗口攻柠,紫色方框是可用窗口:

b441c3f5328a42c6b00ff34b02391aa4.png

在下圖,當發(fā)送方把數(shù)據(jù)「全部」都一下發(fā)送出去后后裸,可用窗口的大小就為 0 了瑰钮,表明可用窗口耗盡,在沒收到 ACK 確認之前是無法繼續(xù)發(fā)送數(shù)據(jù)了微驶。

fbec4c0bf70e4f6991cac1f3464b06f2.png

在下圖浪谴,當收到之前發(fā)送的數(shù)據(jù) 32~36 字節(jié)的 ACK 確認應(yīng)答后,如果發(fā)送窗口的大小沒有變化因苹,則滑動窗口往右邊移動 5 個字節(jié)苟耻,因為有 5 個字節(jié)的數(shù)據(jù)被應(yīng)答確認,接下來 52~56 字節(jié)又變成了可用窗口扶檐,那么后續(xù)也就可以發(fā)送 52~56 這 5 個字節(jié)的數(shù)據(jù)了凶杖。

991afb2eae7e4a4794b85b5b3ac3a7c6.png

TCP 滑動窗口方案使用三個指針來跟蹤在四個傳輸類別中的每一個類別中的字節(jié)。其中兩個指針是絕對指針(指特定的序列號)款筑,一個是相對指針(需要做偏移)智蝠。

ce6a66c5f9254eca8324cf4b57772fc0.png
  • SND.WND:表示發(fā)送窗口的大小(大小是由接收方指定的)奈梳;

  • SND.UNA:是一個絕對指針杈湾,它指向的是已發(fā)送但未收到確認的第一個字節(jié)的序列號,也就是 #2 的第一個字節(jié)攘须。

  • SND.NXT:也是一個絕對指針漆撞,它指向未發(fā)送但可發(fā)送范圍的第一個字節(jié)的序列號,也就是 #3 的第一個字節(jié)。

  • 指向 #4 的第一個字節(jié)是個相對指針浮驳,它需要 SND.NXT 指針加上 SND.WND大小的偏移量悍汛,就可以指向 #4 的第一個字節(jié)了。

可用窗口大小 = SND.WND -(SND.NXT - SND.UNA)

接下來是接收端的窗口

1e87fab0380f4dc5b1dbb102ebee3cf0.png
  • RCV.WND:表示接收窗口的大小至会,它會通告給發(fā)送方员凝。
  • RCV.NXT:是一個指針,它指向期望從發(fā)送方發(fā)送來的下一個數(shù)據(jù)字節(jié)的序列號奋献,也就是 #3 的第一個字節(jié)。
  • 指向 #4 的第一個字節(jié)是個相對指針旺上,它需要 RCV.NXT 指針加上 RCV.WND大小的偏移量瓶蚂,就可以指向 #4 的第一個字節(jié)了。

接收窗口≈發(fā)送窗口

因為滑動窗口是一直在變化的宣吱,假如接收方的應(yīng)用讀取數(shù)據(jù)的速度很快窃这,那么接收窗口就很快就可以騰出空間,但是在把新的接收窗口大小發(fā)給發(fā)送端的時候是存在時延的征候,所以發(fā)送窗口約等于接收窗口杭攻。

流量控制

從上面我們可以知道接收端是有接收窗口的兆解,接收方的應(yīng)用在處理數(shù)據(jù)時也需要一定的時間跑揉,假如發(fā)送方不加以控制锅睛,那么接收方將無法處理過多的數(shù)據(jù)印蔬,導致出發(fā)重傳機制,從而浪費網(wǎng)絡(luò)流量脱衙。

為了解決這種現(xiàn)象發(fā)生陵究,TCP 提供一種機制可以讓「發(fā)送方」根據(jù)「接收方」的實際接收能力控制發(fā)送的數(shù)據(jù)量,這就是所謂的流量控制松蒜。

我們先看看假設(shè)接收窗口和發(fā)送窗口保持200不變的發(fā)送過程:


12b6a363c7a34ce7934bfe3f378e32e5.png
  1. 客戶端發(fā)送請求數(shù)據(jù)報文。
  2. 服務(wù)端接收到請求裁良,發(fā)送確認以及80字節(jié)數(shù)據(jù)膳算,這時發(fā)送窗口的SND.UNA = 241, SND.NXT = SND.WND + 80 = 321旭旭≈蚶ⅲ可用發(fā)送窗口大小 = 200 - ( 321 - 241) = 120悴了。
  3. 客戶端接收到數(shù)據(jù),這時接收窗口RCV.NXT = RCV.NXT + 80 = 321违寿,發(fā)送確認報文温圆。
  4. 發(fā)送端繼續(xù)發(fā)送120個字節(jié)饱搏,由于這時還沒收到客戶端的確認數(shù)據(jù)包推沸,發(fā)送窗口SND.UNA = 241, SND.NXT = 321 + 120 = 441券坞,可用發(fā)送窗口大小 = 200 - (441 - 241) = 0,可用窗口大小為0压怠,這時無法再發(fā)送數(shù)據(jù)眠冈。
  5. 客戶端接收到120字節(jié)數(shù)據(jù),RCV.NXT = 321 + 120 = 441菌瘫,發(fā)送確認報文蜗顽。
  6. 服務(wù)端收到客戶端的第一個確認報文,窗口往右”滑動“80字節(jié)雨让,SND.UNA = 241 + 80 = 321, 可用發(fā)送窗口大小 = 200 - (441 - 321) = 80雇盖。
  7. 服務(wù)端收到客戶端的第二個確認報文,窗口往右”滑動“120字節(jié)栖忠,SND.UNA = 321 + 120 = 441, 可用發(fā)送窗口大小 = 200 - (441 - 441) = 200崔挖。
  8. 服務(wù)端繼續(xù)發(fā)送160個字節(jié)數(shù)據(jù),SND.NXT = 441 + 160 = 601庵寞,可用發(fā)送窗口大小 = 200 - (601 - 441) = 40狸相。
  9. 客戶端接收到數(shù)據(jù),RCV.NXT = 441 + 160 = 601捐川,發(fā)送確認報文脓鹃。
  10. 服務(wù)端收到確認報文,窗口右移160個字節(jié)古沥,SND.UNA = 441 + 160 = 601瘸右,可用發(fā)送窗口大小 = 200 - (601 - 601) = 200。

上面的例子我們假定了發(fā)送窗口和接收窗口是不變的岩齿,但是實際上太颤,發(fā)送窗口和接收窗口中所存放的字節(jié)數(shù),都是放在操作系統(tǒng)內(nèi)存緩沖區(qū)中的盹沈,而操作系統(tǒng)的緩沖區(qū)栋齿,會被操作系統(tǒng)調(diào)整。當應(yīng)用進程沒辦法及時讀取緩沖區(qū)的內(nèi)容時襟诸,也會對我們的緩沖區(qū)造成影響瓦堵。

我們來看下面這個例子:


dd15c2eaed554c5e8d1a6074f9287f9a.png
  1. 客戶端發(fā)送 140 字節(jié)數(shù)據(jù)后,可用窗口變?yōu)?220 (360 - 140)歌亲。
  2. 服務(wù)端收到 140 字節(jié)數(shù)據(jù)菇用,但是服務(wù)端非常繁忙,應(yīng)用進程只讀取了 40 個字節(jié)陷揪,還有 100 字節(jié)占用著緩沖區(qū)惋鸥,于是接收窗口收縮到了 260 (360 - 100)杂穷,最后發(fā)送確認信息時,將窗口大小通過給客戶端卦绣。
  3. 客戶端收到確認和窗口通告報文后耐量,發(fā)送窗口減少為 260。
  4. 客戶端發(fā)送 180 字節(jié)數(shù)據(jù)滤港,此時可用窗口減少到 80廊蜒。
  5. 服務(wù)端收到 180 字節(jié)數(shù)據(jù),但是應(yīng)用程序沒有讀取任何數(shù)據(jù)溅漾,這 180 字節(jié)直接就留在了緩沖區(qū)山叮,于是接收窗口收縮到了 80 (260 - 180),并在發(fā)送確認信息時添履,通過窗口大小給客戶端屁倔。
  6. 客戶端收到確認和窗口通告報文后,發(fā)送窗口減少為 80暮胧。
  7. 客戶端發(fā)送 80 字節(jié)數(shù)據(jù)后锐借,可用窗口耗盡。
  8. 服務(wù)端收到 80 字節(jié)數(shù)據(jù)往衷,但是應(yīng)用程序依然沒有讀取任何數(shù)據(jù)钞翔,這 80 字節(jié)留在了緩沖區(qū),于是接收窗口收縮到了 0炼绘,并在發(fā)送確認信息時,通過窗口大小給客戶端妄田。
  9. 客戶端收到確認和窗口通告報文后俺亮,發(fā)送窗口減少為 0。
    可見最后窗口都收縮為 0 了疟呐,也就是發(fā)生了窗口關(guān)閉脚曾。我們再來看下面的例子:

當服務(wù)端系統(tǒng)資源非常緊張的時候,操心系統(tǒng)可能會直接減少了接收緩沖區(qū)大小启具,這時應(yīng)用程序又無法及時讀取緩存數(shù)據(jù)本讥,會出現(xiàn)數(shù)據(jù)包丟失的現(xiàn)象。


f1d7e77abbda46469059356ab5bef342.png
  1. 客戶端發(fā)送 140 字節(jié)的數(shù)據(jù)鲁冯,于是可用窗口減少到了 220拷沸。
  2. 服務(wù)端因為現(xiàn)在非常的繁忙,操作系統(tǒng)于是就把接收緩存減少了 100 字節(jié)薯演,當收到 對 140 數(shù)據(jù)確認報文后撞芍,又因為應(yīng)用程序沒有讀取任何數(shù)據(jù),所以 140 字節(jié)留在了緩沖區(qū)中跨扮,于是接收窗口大小從 360 收縮成了 100序无,最后發(fā)送確認信息時验毡,通告窗口大小給對方。
  3. 此時客戶端因為還沒有收到服務(wù)端的通告窗口報文帝嗡,所以不知道此時接收窗口收縮成了 100晶通,客戶端只會看自己的可用窗口還有 220,所以客戶端就發(fā)送了 180 字節(jié)數(shù)據(jù)哟玷,于是可用窗口減少到 40狮辽。
  4. 服務(wù)端收到了 180 字節(jié)數(shù)據(jù)時,發(fā)現(xiàn)數(shù)據(jù)大小超過了接收窗口的大小碗降,于是就把數(shù)據(jù)包丟棄了隘竭。
  5. 客戶端收到服務(wù)端發(fā)送的確認報文和通告窗口報文,嘗試減少發(fā)送窗口到 100讼渊,把窗口的右端向左收縮了 80动看,此時可用窗口的大小就會出現(xiàn)詭異的負值。

所以爪幻,如果發(fā)生了先減少緩存菱皆,再收縮窗口,就會出現(xiàn)丟包的現(xiàn)象挨稿。

為了防止這種情況發(fā)生仇轻,TCP 規(guī)定是不允許同時減少緩存又收縮窗口的,而是采用先收縮窗口奶甘,過段時間再減少緩存篷店,這樣就可以避免了丟包情況。

窗口關(guān)閉

如果窗口大小為 0 時臭家,就會阻止發(fā)送方給接收方傳遞數(shù)據(jù)疲陕,直到窗口變?yōu)榉?0 為止,這就是窗口關(guān)閉钉赁。

窗口大小是通過ACK報文發(fā)送的蹄殃,當發(fā)生窗口關(guān)閉時,接收方處理完數(shù)據(jù)后你踩,會向發(fā)送方通告一個窗口非 0 的 ACK 報文诅岩,如果這個通告窗口的 ACK 報文在網(wǎng)絡(luò)中丟失了,那么就會產(chǎn)生“死鎖”:

43313a8faf394caa91e79f5b98a588ff.png

發(fā)送方一直等待接收方的非 0 窗口通知带膜,接收方也一直等待發(fā)送方的數(shù)據(jù)吩谦,如不不采取措施,這種相互等待的過程膝藕,會造成了死鎖的現(xiàn)象逮京。

為了解決這個問題,TCP 為每個連接設(shè)有一個持續(xù)定時器束莫,只要 TCP 連接一方收到對方的零窗口通知懒棉,就啟動持續(xù)計時器草描。

如果持續(xù)計時器超時,就會發(fā)送窗口探測 ( Window probe ) 報文策严,而對方在確認這個探測報文時穗慕,給出自己現(xiàn)在的接收窗口大小。窗口探測的次數(shù)一般為 3 次妻导,每次大約 30-60 秒(不同的系統(tǒng)版本實現(xiàn)可能會不一樣)逛绵。如果探測 3 次過后接收窗口還是 0 的話,有的 TCP 實現(xiàn)就會發(fā) RST 報文來中斷連接倔韭。

aaf3fcf91251423bac05cc99d7488f7a.png

糊涂窗口綜合征

如果接收方太忙了术浪,來不及取走接收窗口里的數(shù)據(jù),那么就會導致發(fā)送方的發(fā)送窗口越來越小寿酌。

到最后胰苏,如果接收方騰出幾個字節(jié)并告訴發(fā)送方現(xiàn)在有幾個字節(jié)的窗口,而發(fā)送方會義無反顧地發(fā)送這幾個字節(jié)醇疼,這就是糊涂窗口綜合癥硕并。

我們的 TCP + IP 頭至少有 40 個字節(jié),假如接收窗口只有幾字節(jié)秧荆,那么就會出現(xiàn)大馬拉小車的情況倔毙,造成資源浪費。

5acc0648ee364bbba1917ea0a662d729.png

參考上圖我們不難想象會有兩種場景導致“大馬拉小車”:

  • 接收端發(fā)送了一個接收窗口很小的ACK包乙濒;
  • 發(fā)送端任性的發(fā)送小數(shù)據(jù)包陕赃。

如何避免發(fā)送小窗口ACK包

當「窗口大小」小于 min( MSS,緩存空間/2 ) 颁股,也就是小于 MSS 與 1/2 緩存大小中的最小值時么库,就會向發(fā)送方通告窗口為 0,也就阻止了發(fā)送方再發(fā)數(shù)據(jù)過來豌蟋。

等到接收方處理了一些數(shù)據(jù)后廊散,窗口大小 >= MSS桑滩,或者接收方緩存空間有一半可以使用梧疲,就可以把窗口打開讓發(fā)送方發(fā)送數(shù)據(jù)過來。

如何防止發(fā)送端發(fā)送小數(shù)據(jù)包

使用 Nagle 算法运准,該算法的思路是延時處理幌氮,它滿足以下兩個條件中的一條才可以發(fā)送數(shù)據(jù)

  • 要等到窗口大小 >= MSS 或是 數(shù)據(jù)大小 >= MSS
  • 收到之前發(fā)送數(shù)據(jù)的 ack 回包

只要沒滿足上面條件中的一條,發(fā)送方就一直囤積數(shù)據(jù)胁澳,直到滿足上面的發(fā)送條件该互。

另外,Nagle 算法默認是打開的韭畸,如果對于一些需要小數(shù)據(jù)包交互的場景的程序宇智,比如蔓搞,telnet 或 ssh 這樣的交互性比較強的程序,則需要關(guān)閉 Nagle 算法随橘。

可以在 Socket 設(shè)置 TCP_NODELAY 選項來關(guān)閉這個算法(關(guān)閉 Nagle 算法沒有全局參數(shù)喂分,需要根據(jù)每個應(yīng)用自己的特點來關(guān)閉)

setsockopt(sock_fd, IPPROTO_TCP, TCP_NODELAY, (char *)&value, sizeof(int));

擁塞控制

可能有的小伙伴會有疑問,前面既然有了流量控制机蔗,為什么還需要一個擁塞控制呢蒲祈?其實細想我們不難發(fā)現(xiàn),流量控制只是避免了發(fā)送方向接收方發(fā)送過多的數(shù)據(jù)萝嘁,防止接收方無法及時響應(yīng)梆掸。他們并不能感知到當前的網(wǎng)絡(luò)狀態(tài)是否擁堵。這就好比平時節(jié)假日出游時牙言,我們總能遇到堵車的情況一樣酸钦,因為在出門的時候我們沒有查詢當前的交通情況,剛好大部分人都選擇在同一天出行嬉挡,那顯然就容易出現(xiàn)交通擁堵的情況了钝鸽。

要解決這個問題也不難,只要大家在出門前先通過APP查詢當前交通狀況庞钢,如果發(fā)現(xiàn)交通已經(jīng)比較擁擠了拔恰,那就選擇改天再出門,選擇錯峰出行基括,那交通出現(xiàn)擁堵的概率就會降低颜懊。

TCP其實也是通過類似的方式去解決網(wǎng)絡(luò)擁塞的,當網(wǎng)絡(luò)發(fā)送擁塞時,TCP 會選擇降低發(fā)送的數(shù)據(jù)量兢仰。

擁塞窗口

在介紹擁塞控制算法前先介紹一個概念蚀瘸,擁塞窗口(CWND)。它是發(fā)送方維護的一個 的狀態(tài)變量咸这,它會根據(jù)網(wǎng)絡(luò)的擁塞程度動態(tài)變化,前面提到過發(fā)送窗口 swnd 和接收窗口 rwnd 是約等于的關(guān)系魔眨,那么由于入了擁塞窗口的概念后媳维,此時發(fā)送窗口的值是swnd = min(cwnd, rwnd),也就是擁塞窗口和接收窗口中的最小值遏暴。

  • 只要網(wǎng)絡(luò)中沒有出現(xiàn)擁塞侄刽,cwnd 就會增大
  • 網(wǎng)絡(luò)中出現(xiàn)了擁塞,cwnd 就減小

接下來我們先解決第一個問題朋凉,TCP怎么知道當前的網(wǎng)絡(luò)是否擁塞呢州丹?

很簡單,只要發(fā)送端沒有在規(guī)定的時間內(nèi)收到ACK應(yīng)答報文(觸發(fā)了超時重傳),那么就認為網(wǎng)絡(luò)出現(xiàn)了擁塞墓毒。

判斷網(wǎng)絡(luò)出現(xiàn)擁塞后吓揪,TCP就會執(zhí)行下面四個算法:

  • 慢啟動
  • 擁塞避免
  • 擁塞發(fā)生
  • 快速恢復
慢啟動

TCP在連接建立之時,會通過慢啟動的方式逐漸增加發(fā)送數(shù)據(jù)量所计。慢啟動算法核心是:當發(fā)送方每收到一個 ACK磺芭,就擁塞窗口 cwnd 的大小就會加 1。假定擁塞窗口 cwnd 和發(fā)送窗口 swnd 相等醉箕。

  • 連接建立完成后钾腺,一開始初始化 cwnd = 1,表示可以傳一個 MSS(MSS就是連接請求時在報頭設(shè)置的字段)大小的數(shù)據(jù)讥裤。
  • 當收到一個 ACK 確認應(yīng)答后放棒,cwnd 增加 1,于是一次能夠發(fā)送 2 個
  • 當收到 2 個的 ACK 確認應(yīng)答后己英, cwnd 增加 2间螟,于是就可以比之前多發(fā)2 個,所以這一次能夠發(fā)送 4 個
  • 當這 4 個的 ACK 確認到來的時候损肛,每個確認 cwnd 增加 1厢破, 4 個確認 cwnd 增加 4,于是就可以比之前多發(fā) 4 個治拿,所以這一次能夠發(fā)送 8 個摩泪。
64e25531483f45609e8afab1cbf13659.png

慢啟動窗口是呈指數(shù)增長的,如果任由它一直增長下去毫無疑問網(wǎng)絡(luò)會出現(xiàn)擁堵劫谅,所以TCP設(shè)置了一個閾值见坑,它就是慢啟動門限 ssthresh (slow start threshold)狀態(tài)變量。

  • 當 cwnd < ssthresh 時捏检,使用慢啟動算法荞驴。
  • 當 cwnd >= ssthresh 時,就會使用「擁塞避免算法」贯城。
擁塞避免算法

當擁塞窗口 cwnd 「超過」慢啟動門限 ssthresh 就會進入擁塞避免算法熊楼。一般來說 ssthresh 的大小是 65535 字節(jié)。進入擁塞避免算法后能犯,它的規(guī)則是:每當收到一個 ACK 時鲫骗,cwnd 增加 1/cwnd。

接上前面的慢啟動的例子悲雳,假定 ssthresh 為 8:

當 8 個 ACK 應(yīng)答確認到來時挎峦,每個確認增加 1/8香追,8 個 ACK 確認 cwnd 一共增加 1合瓢,于是這一次能夠發(fā)送 9 個 MSS 大小的數(shù)據(jù),變成了線性增長透典。

7755f60e427b4ed2bdd1aa769b8512cd.png

擁塞避免算法就是將原本慢啟動算法的指數(shù)增長變成了線性增長晴楔。

隨著發(fā)送量增大顿苇,網(wǎng)絡(luò)慢慢就會出現(xiàn)擁塞,這時候就會出現(xiàn)丟包税弃,進而觸發(fā)重傳纪岁。當觸發(fā)重傳機制,那么就會啟動擁塞發(fā)生算法则果。

擁塞發(fā)生

需要注意的是幔翰,上面我們介紹過兩種重傳機制:

  • 超時重傳
  • 快速重傳

這兩種重傳機制對應(yīng)兩種不同的異常:超時重傳是網(wǎng)絡(luò)出現(xiàn)擁堵,無法快速處理所有數(shù)據(jù)包西壮,所以導致數(shù)據(jù)包“堵”在網(wǎng)絡(luò)當中遗增;而快速重傳是由于網(wǎng)絡(luò)異常從而導致某一個數(shù)據(jù)包“失蹤”了,而網(wǎng)絡(luò)實際是暢通的款青。

因此針對這兩種異常做修,TCP同樣選擇兩種算法處理:

擁塞發(fā)生<=>超時重傳

  • ssthresh 設(shè)為 cwnd/2,
  • cwnd 重置為 1
6310fe3872a04422bd251960507a06d1.png

從圖中不難看出抡草,這種算法呈現(xiàn)的是“斷崖式下跌”(還好不是股市)饰及。如果只采用這種擁塞發(fā)生算法的話,那么網(wǎng)絡(luò)的波動就會非常大康震,體現(xiàn)在打游戲時突然延遲很高~~

接下來就介紹針對快速重傳的擁塞發(fā)生算法——快速恢復燎含,因為發(fā)送方還能連續(xù)收到3個ACK,說明網(wǎng)絡(luò)情況還比較樂觀腿短。ssthresh 和cwnd 變化如下:

  • cwnd = cwnd/2 瘫镇,也就是設(shè)置為原來的一半;
  • ssthresh = cwnd;
快速恢復
  • 擁塞窗口 cwnd = ssthresh + 3 ( 3 的意思是確認有 3 個數(shù)據(jù)包被收到了)
  • 重傳丟失的數(shù)據(jù)包
  • 如果再收到重復的 ACK,那么 cwnd 增加 1
  • 如果收到新數(shù)據(jù)的 ACK 后答姥,設(shè)置 cwnd 為 ssthresh铣除,接著就進入了擁塞避免算法
25061b045a9c4883a879a48d57635f6f.png

四次揮手說再見

823435-20170323093037486-665986934.png

MSL是Maximum Segment Lifetime的英文縮寫,可譯為“最長報文段壽命”鹦付,它是任何報文在網(wǎng)絡(luò)上存在的最長的時間尚粘,超過這個時間報文將被丟棄。我們都知道IP頭部中有個TTL字段敲长,TTL是time to live的縮寫郎嫁,可譯為“生存時間”,這個生存時間是由源主機設(shè)置初始值但不是存在的具體時間祈噪,而是一個IP數(shù)據(jù)報可以經(jīng)過的最大路由數(shù)泽铛,每經(jīng)過一個路由器,它的值就減1辑鲤,當此值為0則數(shù)據(jù)報被丟棄盔腔,同時發(fā)送ICMP報文通知源主機。RFC793中規(guī)定MSL為2分鐘,但這完全是從工程上來考慮弛随,對于現(xiàn)在的網(wǎng)絡(luò)瓢喉,MSL=2分鐘可能太長了一些。因此TCP允許不同的實現(xiàn)可根據(jù)具體情況使用更小的MSL值舀透。TTL與MSL是有關(guān)系的但不是簡單的相等關(guān)系栓票,MSL要大于TTL。
在TIME_WAIT狀態(tài)時兩端的端口不能使用愕够,要等到2MSL時間結(jié)束才可繼續(xù)使用走贪。當連接處于2MSL等待階段時任何遲到的報文段都將被丟棄。不過在實際應(yīng)用中可以通過設(shè)置SO_REUSEADDR選項達到不必等待2MSL時間結(jié)束再使用此端口惑芭。

當客戶端沒有東西要發(fā)送時就要釋放連接厉斟,客戶端會發(fā)送一個報文(沒有數(shù)據(jù)),其中 FIN 設(shè)置為1, 服務(wù)端收到后會恢復確認强衡,這時客戶端的連接已經(jīng)關(guān)閉擦秽,即客戶端不再發(fā)送信息(但仍可接收信息)。 客戶端收到確認后進入等待狀態(tài)漩勤,等待服務(wù)端請求釋放連接感挥, 服務(wù)端數(shù)據(jù)發(fā)送完畢后就向客戶端請求連接釋放,同樣是用FIN=1 表示越败, 并且用 ack = u+1(如圖)触幼, 客戶端收到后同樣回復一個確認,并進入 TIME_WAIT 狀態(tài)究飞, 等待 2MSL 時間置谦。

為什么需要等待?

因為服務(wù)端接收到釋放連接的請求后會發(fā)送確認信息亿傅,這個確認信息是有可能丟失的媒峡,所以客戶端就需要等待,如果超時還沒收到確認葵擎,那么就會再次發(fā)送釋放連接的請求谅阿。

為什么客戶端在FIN-WAIT-2階段發(fā)送ACK后還需要等待2MSL

1.為了保證客戶端(我們記為A端)發(fā)送的最后一個ACK報文段能夠到達服務(wù)器端。這個ACK報文段有可能丟失酬滤,因而使處在LASK—ACK端的服務(wù)器端(我們記為B端)收不到對已發(fā)送的FIN+ACK報文段签餐。B會超時重傳這個FIN+ACK報文段,而A就能在2MSL時間內(nèi)收到這個重傳的FIN+ACK報文段盯串。接著A重傳一次確認氯檐,重新啟動2MSL計時器。最后体捏,A和B都正常進入到CLOSED狀態(tài)冠摄。如果A在TIME_WAIT狀態(tài)不等待一段時間糯崎,而是在發(fā)送完ACK確認后立即釋放連接,那么就無法收到B重傳的FIN+ACK報文段耗拓,因而也不會再發(fā)送一次確認報文段,這樣奏司,B就無法正常進入CLOSED狀態(tài)乔询。

2.我們都知道,假如A發(fā)送的第一個請求連接報文段丟失而未收到確認韵洋,A就會重傳一次連接請求竿刁,后來B收到了確認,建立了連接搪缨。數(shù)據(jù)傳輸完畢后食拜,就釋放了連接。A共發(fā)送了兩個連接請求報文段副编,其中第一個丟失负甸,第二個到達了B。假如現(xiàn)在A發(fā)送的第一個連接請求報文段沒有丟失痹届,而是在某些網(wǎng)絡(luò)節(jié)點長時間都留了呻待,以至于延誤到連接釋放后的某個時間才到達B,這本來是已失效的報文段队腐,但B并不知道蚕捉,就會又建立一次連接。而等待的這2MSL就是為了解決這個問題的柴淘,A在發(fā)送完最后一個確認報后迫淹,在經(jīng)過時間2MSL,就可以使本鏈接持續(xù)時間內(nèi)所產(chǎn)生的所有報文段都從網(wǎng)絡(luò)中消失为严,這樣就可以使下一個新的連接中不會出現(xiàn)這種舊的連接請求報文段敛熬。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市第股,隨后出現(xiàn)的幾起案子荸型,更是在濱河造成了極大的恐慌,老刑警劉巖炸茧,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瑞妇,死亡現(xiàn)場離奇詭異,居然都是意外死亡梭冠,警方通過查閱死者的電腦和手機辕狰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來控漠,“玉大人蔓倍,你說我怎么就攤上這事悬钳。” “怎么了偶翅?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵默勾,是天一觀的道長。 經(jīng)常有香客問我聚谁,道長母剥,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任形导,我火速辦了婚禮环疼,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘朵耕。我一直安慰自己炫隶,他們只是感情好,可當我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布阎曹。 她就那樣靜靜地躺著伪阶,像睡著了一般。 火紅的嫁衣襯著肌膚如雪处嫌。 梳的紋絲不亂的頭發(fā)上望门,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天,我揣著相機與錄音锰霜,去河邊找鬼筹误。 笑死,一個胖子當著我的面吹牛癣缅,可吹牛的內(nèi)容都是我干的厨剪。 我是一名探鬼主播,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼友存,長吁一口氣:“原來是場噩夢啊……” “哼祷膳!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起屡立,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤直晨,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后膨俐,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體勇皇,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年焚刺,在試婚紗的時候發(fā)現(xiàn)自己被綠了敛摘。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡乳愉,死狀恐怖兄淫,靈堂內(nèi)的尸體忽然破棺而出屯远,到底是詐尸還是另有隱情,我是刑警寧澤捕虽,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布慨丐,位于F島的核電站,受9級特大地震影響泄私,放射性物質(zhì)發(fā)生泄漏房揭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一挖滤、第九天 我趴在偏房一處隱蔽的房頂上張望崩溪。 院中可真熱鬧浅役,春花似錦斩松、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至瞪讼,卻和暖如春钧椰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背符欠。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工嫡霞, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人希柿。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓诊沪,卻偏偏與公主長得像,于是被迫代替她去往敵國和親曾撤。 傳聞我的和親對象是個殘疾皇子端姚,可洞房花燭夜當晚...
    茶點故事閱讀 43,490評論 2 348

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

  • TCP協(xié)議簡介 TCP協(xié)議是在TCP/IP協(xié)議模型中的運輸層中很重要的一個協(xié)議、負責處理主機端口層面之間的數(shù)據(jù)傳輸...
    吃大米的小螞蟻閱讀 1,769評論 0 2
  • TCP/IP詳解 網(wǎng)絡(luò)協(xié)議通常分不同層次進行開發(fā)挤悉,每一層分別負責不同的通信功能一個協(xié)議族渐裸,比如TCP/IP,是一組...
    謎碌小孩閱讀 1,245評論 0 5
  • 概述 TCP/IP 協(xié)議棧是一系列網(wǎng)絡(luò)協(xié)議的總和装悲,是構(gòu)成網(wǎng)絡(luò)通信的核心骨架昏鹃,它定義了電子設(shè)備如何連入因特網(wǎng),以及數(shù)...
    醬紫_Johns閱讀 520評論 0 0
  • 為什么會有TCP/IP協(xié)議 在世界上各地诀诊,各種各樣的電腦運行著各自不同的操作系統(tǒng)為大家服務(wù)盆顾,這些電腦在表達同一種信...
    RaphetS閱讀 278,968評論 12 294
  • 久違的晴天,家長會畏梆。 家長大會開好到教室時您宪,離放學已經(jīng)沒多少時間了奈懒。班主任說已經(jīng)安排了三個家長分享經(jīng)驗。 放學鈴聲...
    飄雪兒5閱讀 7,513評論 16 22