文章目錄
- 作用
- 傳輸内容
- 傳輸層協定
-
- TCP
-
- 三次握手
- 四次揮手
-
- 為什麼建立連接配接協定是三次握手,而關閉連接配接卻是四次握手呢?
- 為什麼 TIME_WAIT 狀态還需要等 2MSL 後才能傳回到 CLOSED 狀态?
- 如果已經建立連接配接,但是用戶端突然出現了故障會怎麼辦?
- 采用兩次握手行不行?
- 可靠的資料傳輸
-
- 發送方滑動距離問題
- 逾時重傳時間問題
- 擁塞控制
-
- 快重傳與快恢複問題
- 流量控制
- UDP
-
- TCP和UDP的差別
- 裝置實作
作用
傳輸層提供應用程式之間的邏輯通信機制。
傳輸内容
封包段/資料段(Segment/UPD Datagram):傳輸層将封包分組稱為封包段。
TCP的封包段就叫封包段(Segment)。
UDP的封包段叫資料段也叫UDP資料報(UDP datagram)
封包段通常指起始點和目的地都是傳輸層的資訊單元。
傳輸層協定
TCP
- 面向連接配接:TCP連接配接
三次握手
位碼即tcp标志位,有6種标示:SYN(synchronous建立聯機) ACK(acknowledgement 确認) PSH(push傳送) FIN(finish結束) RST(reset重置) URG(urgent緊急)
TCP序列号(seq number):發送的TCP的序号,從0開始,實際中這個值就是發送的資料報中内容的位元組數,比如我發送的第一個報中sq=0,資料報内容20位元組,那麼下一個資料報的sq就應該是21。
确認号(ack number):确認收到上一個資料報,然後ack的值是指定自己想要收到的下一個資料報的sq,比如我收到一個資料報的sq=0,資料報内容20位元組,那麼我的ack就應該是21,用來标明我sq=0,内容為20位元組的資料報已經收到,我接下來期望收到的是sq=21的資料報。
-
第一次握手
用戶端A向伺服器B發送位碼為SYN=1(聯機請求),随機産生seq number=1234567。
用戶端進入SYN_SEND狀态。
-
第二次握手
伺服器B向主機A發送位碼ack=1(聯機确認),序列确認ack number=A序列号+1。
伺服器B同時向主機A發送位碼SYN(聯機請求),随機産生seq number=7654321。
伺服器進入SYN_RECV狀态
-
第三次握手
用戶端A向伺服器B發送位碼ack=1(聯機确認),序列确認ack number=B序列号+1。
用戶端同時向伺服器B發送序列号seq number=A序列号+1。
用戶端和伺服器進入ESTABLISHED狀态。
四次揮手
由于TCP是雙共的,是以有兩條信道需要斷開。
-
第一次揮手
用戶端A向伺服器B發送位碼FIN=1(結束請求)。
-
第二次揮手
伺服器B向用戶端A發送位碼ACK=1(結束确認)。
-
第三次揮手
伺服器B向用戶端A發送位碼FIN=1(結束請求)。
-
第四次揮手
用戶端A向伺服器B發送位碼ACK=1(結束确認)。
TCP連接配接的十一種狀态參考這裡
為什麼建立連接配接協定是三次握手,而關閉連接配接卻是四次握手呢?
這是因為三次握手的時候,服務端在的 LISTEN 狀态下的 socket 當收 到 SYN 封包的建立連接配接請求後,它可以把 ACK 和 SYN 放在一個封包裡來發送。
但關閉連接配接時, 當收到對方的 FIN 封包通知時,它僅僅表示對方沒有資料發送給你了;是以你可以立馬發送ack确認用戶端到伺服器的連接配接斷開。
但未必你所有的資料都全部發送給對方了,是以你可能還需要發送一些資料給對方之後,再發送 FIN 封包給對方來表示請求關閉伺服器到用戶端的連接配接。
是以它這裡的 ACK 封包 和 FIN封包多數情況下都是分開發送的。
為什麼 TIME_WAIT 狀态還需要等 2MSL 後才能傳回到 CLOSED 狀态?
這是因為雖然雙方都同意關閉連接配接了,而且揮手的 4 個封包也都協調和發送完畢,按理可以直接回到 CLOSED 狀态;
但是因為我們必須要假想網絡是不可靠的,你無法保證你最後發送的 ACK 封包會一定被對方收到。
也就是伺服器處于 LAST_ACK 狀态下的 SOCKET ,可能因為逾時未收到 ACK 封包而重發 FIN 封包。
這個 TIME_WAIT 狀态的作用 就是用來重發可能丢失的 ACK 封包。
至于為什麼是2MSL參考這裡
如果已經建立連接配接,但是用戶端突然出現了故障會怎麼辦?
TCP還設有一個保活機制。顯然,如果用戶端出現了故障,服務端不能一直等下去。若等了一段時間還沒有收到用戶端的任何資料,服務端就會發送一個探測封包段,若一連發送10個探測封包段仍然沒有反應,服務端就認為是用戶端出現了故障,就會關閉連接配接。
采用兩次握手行不行?
- 采用三次握手是為了防止失效的連接配接請求封包段突然又傳送到主機B,因而産生錯誤。失效的連接配接請求封包段是指:主機A發出的連接配接請求沒有收到主機B的确認,于是經過一段時間後,主機A又重新向主機B發送連接配接請求,且建立成功,順序完成資料傳輸之後斷開。
- 此時,主機A第一次發送的連接配接請求并沒有丢失,而是因為網絡節點導緻延遲達到主機B,主機B以為是主機A又發起的新連接配接,于是主機B同意連接配接,并向主機A發回确認,但是此時主機A根本不會理會,主機B就一直在等待主機A發送資料,導緻主機B的資源浪費。
可靠的資料傳輸
ARQ協定和滑動視窗協定參考這裡
發送方滑動距離問題
文中有言:
連續ARQ協定規定,發送方每收到一個确認,就把發送視窗向前滑動一個分組的位置。如果原來已經發送了前5個分組,則現在可以發送視窗内的第6個分組。
接收方一般都是采用累積确認的方式。也就是說接收方不必對收到的分組逐個發送确認。而是在收到幾個分組後,對按序到達的最後一個分組發送确認。如果收到了這個分組确認資訊,則表示到這個分組為止的所有分組都已經正确接收到了。
這裡是有一個沖突的,接收方不會确認每個分組,隻确認最後一個。那麼發送方就不會一次向前滑動一個分組的位置了。而是每次向前滑動視窗大小個位置。如下
逾時重傳時間問題
文中有言:
逾時重傳的原理也很簡單:發送方發送完一個分組後,就會設定一個逾時計時器,如果逾時計時器到期之前沒有收到接收方發來的确認資訊,則會重發剛發送過的分組;如果收到确認資訊,則撤銷該逾時計時器。
這裡其實涉及到一個概念,TCP連接配接的往返時間 RTT及計時器的逾時時間RTO。
RTT和ROT的概念可以參考這裡
擁塞控制
- 先整體了解一下什麼是擁塞。
- 擁塞(非正式定義):主機發送了太多資料或者發送過快導緻網絡無法處理。
- 擁塞控制:當網絡負載過重時限制發送方的發送速度。
擁塞控制方法可以參考這裡
快重傳與快恢複問題
文中對快重傳與恢複問題沒講到位。
如果發送方設定的逾時計時器逾時害沒有收到确認,就很可能是出現了擁塞。即M2确認了之後,M3丢了。
這時,慢啟動與擁塞避免的做法是:
- 把慢開始門限 ssthresh 設定為出現擁塞時的發送方視窗值的一半(但不能小于2)。然後把擁塞視窗 cwnd 重新設定為 1,執行慢開始算法。
這時,快重傳與快恢複的做法是:
- 接收方收到M4後判斷有一個失序封包段,就立即發出重複确認,而不要等到自己發送資料時才進行捎帶确認,這樣可以使發送方及早知道有封包段沒有到達對方。發送方接着發送了M5和M6。接收方收到這兩個封包後,也還要再次發出對M2的重複确認。這樣,發送方共收到了接收方的四個對M2的确認,其中後三個都是重複确認。快重傳算法還規定,發送方隻要一連收到三個重複确認就應當立即重傳對方尚未收到的封包段M3,而不必繼續等待M3設定的重傳計時器到期。由于發送方盡早重傳未被确認的封包段,是以采用快重傳後可以使整個網絡吞吐量提高約20%。
與快重傳配合使用的還有快恢複算法,其過程有以下兩個要點:
- 當發送方連續收到三個重複确認,就執行“乘法減小”算法,把慢開始門限ssthresh減半。這是為了預防網絡發生擁塞。請注意:接下去不執行慢開始算法。
- 由于發送方現在認為網絡很可能沒有發生擁塞,是以與慢開始不同之處是現在不執行慢開始算法(即擁塞視窗cwnd現在不設定為1),而是把cwnd值設定為慢開始門限ssthresh減半後的數值,然後開始執行擁塞避免算法(“加法增大”),使擁塞視窗緩慢地線性增大。
流量控制
流量控制(flow control)就是讓發送方的發送速率不要太快,既要讓接收方來得及接收,也不要使網絡發生擁塞。利用滑動視窗機制可以很友善地在 TCP 連接配接上實作流量控制。
- 設A向B發送資料。在連接配接建立時,B告訴了A:“我的接收視窗是 rwnd = 400 ”(這裡的 rwnd 表示 receiver window) 。是以,發送方的發送視窗不能超過接收方給出的接收視窗的數值。請注意,TCP的視窗機關是位元組,不是封包段。TCP連接配接建立時的視窗協商過程在圖中沒有顯示出來。再設每一個封包段為100位元組長,而資料封包段序号的初始值設為1。大寫ACK表示首部中的确認位ACK,小寫ack表示确認字段的值ack。
- 從圖中可以看出,B進行了三次流量控制。第一次把視窗減少到 rwnd = 300 ,第二次又減到了 rwnd = 100 ,最後減到 rwnd = 0 ,即不允許發送方再發送資料了。這種使發送方暫停發送的狀态将持續到主機B重新發出一個新的視窗值為止。B向A發送的三個封包段都設定了 ACK = 1 ,隻有在ACK=1時确認号字段才有意義。
零視窗處理——持續計數器
- 考慮上面的例子中,當A發送的資料已經到達B的接收視窗上限,此時A就必須等待B處理了部分資料後,待接收視窗有空閑的時候,再次發送資料,那麼A是怎麼知道B的接收視窗何時有空閑呢?這時就用到了持續計時器。
- TCP 為每一個連接配接設有一個持續計時器。隻要 TCP 連接配接的一方收到對方的零視窗通知,就啟動持續計時器。若持續計時器設定的時間到期,就發送一個零視窗探測封包段(僅攜帶 1 位元組的資料),而對方就在确認這個探測封包段時給出了現在的視窗值。若視窗仍然是零,則收到這個封包段的一方就重新設定持續計時器。若視窗不是零,則死鎖的僵局就可以打破了。
-
不提供
延遲保障
帶寬保障
UDP
- 無連接配接
- 不可靠的資料傳輸
-
不提供
流量控制
擁塞控制
延遲保障
帶寬保障
TCP和UDP的差別
裝置實作
發送方:将應用遞交的消息分成一個或多個Segment,并向下傳輸給網絡層
接收方:将接收到的segment組裝成消息,并向上交給應用層。