天天看點

TCP協定之差錯控制

說明: 本文僅供學習交流,轉載請标明出處,歡迎轉載!

 本文是以下文獻相關内容的總結

[1] 《TCP/IP詳解 卷1:協定》

[2] 《TCP/IP協定族 第4版》

[3] 《計算機網絡 第5版》

        TCP是一種面向連接配接的、可靠的、基于位元組流的協定。可靠性指的是發送應用程式把資料流傳遞給TCP後,能夠把資料流按序地、無差錯地交給接收端的接收端的應用程式。TCP通過差錯控制來提供可靠性,TCP差錯控制包括:(1)檢測并重傳受損傷的封包段;(2)重傳丢失的封包段;(3)丢棄重傳的封包段并重傳該封包段的ACK;(4)保證接收緩沖區的封包段按序交給接收端的應用程式。

       FAQ1:TCP如何檢測資料報是否損傷?

        TCP接收端在收到封包段後,在封包段的首部加上僞首部後,連同資料部分一塊計算檢驗和,如果計算結果為全1,說明資料沒有收到損傷。

       FAQ2:接收方在什麼時候産生ACK封包段? 

       (1)當接收方收到發送方發來的按序到達的封包段時,就發送過一個ACK封包段;

       (2)當收到的封包段的序号比期望的封包段的序号大時,接收方立即發送之前那個為收到的序号(即還是之前那個期望的序号);

       (3)接收方收到一個重複的封包段時,丢棄該封包段,并立即向發送端發送該封包段的ACK。

       FAQ3:發送方何時重傳?

        情況一:當發送方發送一個資料段出去時,會啟動重傳計時器,若在RTO内沒有收到該資料段的ACK,則發送端則重傳該資料段,該情況叫逾時重傳;

        情況二:當發送端收到接收端發送過來的三個對重複的ACK時(即三個期望收到的封包段相同時),即便RTO為到時,發送端也重傳接收方期望的那個資料段,該情況叫快重傳。

       FAQ4:接收方如何處理失序到達的封包段?

        TCP并不會丢棄失序到達的封包段,而是将這些失序達到的封包段臨時存放在接收緩沖區,并把它們标志位失序封包段,直到确實的封包段到齊。一定要記住:TCP永遠都不會将失序的封包段交給接收程序。

       FAQ5:發送端與接收端何時可能産生死鎖現象?TCP是如何解決該死鎖僵局的?

       當接收端向發送端發送一個零視窗封包段(封包段首部中視窗值的大小設定為0),發送端就停止向接收端發送封包段。後來接收端想通知發送端,讓發送端接着發送資料時,便向發送端發送一個非零視窗封包段。不幸的是,該封包段在路上丢失了。而接收端以為該非零封包段已經發送給發送端,于是便傻乎乎地等待發送端發送資料過來。而發送端由于沒有收到接收方的非零視窗封包段,于是便在那安逸地休息,随時等待接收方的非零視窗封包的通知。于是兩端都傻乎乎地等,陷入“死鎖”的狀态。

       為了避免這一死鎖的狀态,TCP為發送端設定了一個持續計時器(persistent timer),當發送端收到接收端發來的零視窗封包段時,并啟動該持續計時器,便等待着接收方的非零通知。如果一直沒收到接收方的通知,持續計時器又逾時了的時候,發送端便向接收方發送一個“探測封包段”,該探測封包僅攜帶1B的資料,該探測封包會消耗一個序号,但特殊的是,該探測封包段的序号永遠不需要确認。該探測封包段的目的是僅僅是促使TCP接收端重傳一個确認,該确認的内容包括接收端希望發送端的發送視窗的大小作為回複,即:如果接收端希望發送端的視窗大小仍然是0,那麼發送端在收到該确認封包後,便會重置該持續計時器;如果接收方期望發送發的視窗不是0,則該僵局便打破了。

      注意:即便發送發收到了零視窗設定的封包段,發送端也能接收這幾種封包段:探測封包段、ACK封包段和攜帶緊急資料的封包段。