計算機網路——傳輸層(三)
TCP協議
傳送端應用程式通過套接字介面將資料傳向傳輸層之後,這些資料就歸傳輸層管了,這裡就是TCP協議。TCP協議會管理一個傳送快取,所有通過套接字介面的資料會被放到這個傳送快取中去,然後TCP每次從這個快取中拿出資料,將資料傳遞到網路層。其實這個過程就是多路複用。
我們可以這麼理解,把整個過程想象成一個快遞系統,我們每家每戶就相當於應用程式,當我們要寄快遞的時候,我們是不是要把快遞交給快遞員,這裡這個快遞員就相應於套接字。我們的快遞是通過快遞員傳遞的嗎?當然不是,快遞員會把每個收集的快遞包裹放到一個分發中心,然後通過物流來運輸快遞。這裡的這個分發中心就相當於TCP協議的傳送快取。
這些傳送快取中的資料是被多次運輸才最終被送走的,就像在分發中心有十幾噸的貨物,但我的貨車最多隻能運輸一噸的貨物,那麼就只能將貨物打包成一個個一噸重的包裹再通過貨車進行運輸。在TCP協議中也是一樣,TCP每次能從發生快取中取出資料的上限叫做最大報文長度(MSS),這個MSS由你自己主機的傳送能力所決定。TCP會為每個取出的資料段加上一個TCP首部,這個TCP首部會指示這個資料的一些資訊,比如要傳向哪裡,序列號等等。需要注意的是,MSS指的是資料段的最大長度,並不是指包括TCP首部的TCP報文段。
1.TCP報文段結構
- 源埠號
- 目的埠號
- 序號
- 確認號
- 檢驗和
- 接受視窗
- 資料段
源埠號和目的埠號都是16位元字,也就是說埠號的長度為2^16 -1 = 65535。也就是說可用埠號是0~65535。其中0到1023是周知埠號,也就是某些特定的應用程式所要使用的,比如HTTP用的是80埠,DNS用的是53埠等等。所以一般的應用程式被分配的埠號會從1024開始分配。
序號指的是資料位元組流的位元組號,用Seq表示。比如資料是1000個位元組,而MSS大小為100位元組,則第一個報文序號為0,第二個報文序號是0+100=100,而不是0+1=1。第三個報文序號就是100+100=200了。序號指的是位元組流首位元組的位元組號,而不是指這是第幾個位元組流。
確認號是主機A期望從主機B收到的下一位元組的序號,用ACK表示。比如主機A已經收到序號為500的報文段,則主機A會發送一個確認號為501的響應報文,表示已經收到了500之前的所有報文段,期待收到從501開始的報文段。確認號對於TCP傳輸資料可靠協議來說是非常重要的。
檢驗和是用來檢測資料是否發生損失的。
接收視窗是用來為流量控制服務的,流量控制我會在下文講到。
資料段就是TCP從傳送快取中取出的資料。
流量控制
一條TCP連線的每一側主機都會為該連線設定接收快取(類比之前的傳送快取)。TCP協議將接收到的資料放到接收快取中,需要的應用程式從該快取中取走資料。需要注意的是,應用程式並不是每次資料一到達就立即取走,而是在自己需要的都是才去拿走資料。所以如果應用程式取走的比較少,而TCP協議接收的比較多,久而久之,這個接收快取就會被填滿,導致接收快取傳送溢位。
為了避免這個情況,TCP協議提供了流量控制服務。TCP協議在報文首部增加接收視窗(rwnd)欄位用來指示接收快取中空閒區的大小。只要保證傳送端傳送的資料量控制在接收視窗大小之內,就不會使對方接收快取發生溢位現象。
擁塞控制
首先我們得知道什麼是擁塞,擁塞指的是網路中傳輸的資料達到了承載上限,有可能會導致資料丟包的發生。
我們知道網路資料的傳輸是經過一個個路由器的,路由器接收傳入資料,通過將傳入資料導向指定的資料鏈路。路由器會管理一個快取佇列,當從鏈路中導向路由器資料的速率大於路由器匯出速率的時候,路由器會將多出來的資料放到快取佇列中。但這個快取空間也是有限的,如果快取空間已滿,這時新到來一個數據。那麼這個資料或者快取佇列中的某個資料就會被丟棄,從而導致丟包。
因為TCP協議是可靠的資料傳輸協議,所有當丟包發生的時候,TCP協議會讓發生端重新發送丟失的資料包,並且降低傳送速率,因為丟包的發生已經說明當前速率超過了網路承載的上限。TCP協議用擁塞視窗(cwnd)(類比之前的接收視窗)來控制傳送速率。
那麼如何知道丟包的發生呢?一種方法是檢測超時,就是我這個資料包傳送一段時間後仍未檢測到確認訊號,那麼就說明這個資料包已經丟失。另一種情況是當我收到多個冗餘確認訊號時,也說明有丟包的發生。這個傳送在流水線可靠傳輸協議的情況下。可以這麼理解,主機A成功傳送序號為100的報文段給主機B,主機B會反饋確認號為101的報文段給主機A,說明報文100已經收到,期待報文101。主機A接著傳送序號為101的報文,這個報文在網路中發生丟包。在流水線傳輸協議中,主機A會繼續傳輸接下來的報文,也就是序號為102,103…的報文,但報文數量不會超過視窗值(這個視窗值是之前設定過的)。當主機B接收到報文102時發現報文101還未送到,所以仍會發送確認訊號101給主機A,並把報文102放到快取視窗中去;同理,當主機B接收到報文103時發現報文101仍未送達,所以依然會發送確認訊號101。那麼對於主機A來說,它就接收到了多次相同的101確認訊號,我們稱之為冗餘訊號。主機A就會得出判斷,報文101已經發生丟包。