《計算機網絡自頂向下方法》學習筆記——2、運輸層

目錄

1、多路複用與多路分解

2、UDP

3、TCP


1、多路複用與多路分解

       將主機間交付擴展到進程間交付被稱爲運輸層的多路複用與多路分解:

        一個進程有一個或多個套接字,它相當於從網絡向進程傳遞數據和從進程向網絡傳遞數據的門戶。因此,在接收主機中的運輸層實際上並沒有直接將數據交付給進程,而是將數據交給了一箇中間的套接字。

       每個運輸層報文段中具有幾個字段,在接收端,運輸層檢查這些字段,標識出接收套接字,進而將報文段定向到該套接字。將運輸層報文段中的數據交付到正確的套接字的工作稱爲多路分解。在源主機從不同套接字中收集數據塊,併爲每個數據塊封裝上首部信息(這將在以後用於分解)從而生成報文段,然後將報文段傳遞到網絡層,所有這些工作稱爲多路複用。

  1. 無連接的多路複用與多路分解

       一個UDP套接字是由一個二元組來全面標識的,該二元組包含一個目的IP地址和一個目的端口號。因此,如果兩個UDP報文段有不同的源IP地址和/或源端口號,但具有相同的目的IP地址和目的端口號,那麼這兩個報文段將通過相同的目的套接字被定向到相同的目的進程。

      2. 面向連接的多路複用與多路分解

       TCP套接字是由一個四元組(源IP地址,源端口號,目的IP地址,目的端口號)來標識的。特別與UDP不同的是,兩個具有不同源IP地址或源端口號到達TCP報文段將被定向到兩個不同的套接字,除非TCP報文段攜帶了初始創建鏈接的請求。

 

這裏有一個思考:UDP的socket是二元組而TCP的是四元組的本質原因就是UDP是無連接的,發就完事了,而TCP是面向連接的,不可能同時幾臺主機與同一個socket建立連接。

 

2、UDP

       UDP只是做了運輸協議能夠做的最少工作。除了複用/分解功能及少量的差錯檢測外,它幾乎沒有對IP增加別的東西。許多應用更適合UDP的原因主要有以下幾點:

  1. 關於何時、發送什麼數據的應用層控制更爲精細。採用UDP時,只要應用進程將數據傳遞給UDP,UDP就會將此數據打包進UDP報文段並立即將其傳遞給網絡。實時應用通常不希望過分地延遲報文段的發送,並且能容忍一些數據的丟失,TCP服務模型不是特別適合這些應用。
  2. 無需連接建立。UDP不需要任何準備即可進行數據傳輸。因此UDP不會引入建立連接的時延。
  3. 無連接狀態。連接狀態包括接收和發送緩存、擁塞控制參數以及需要和確認號的參數。要實現TCP的可靠數據傳輸服務並提供擁塞控制,這些狀態信息是必要的。UDP不維護連接狀態,即不跟蹤這些參數,因此,某些服務器當應用程序運行在UDP之上而不是TCP之上時,一般都能支持更多的活躍客戶。
  4. 分組首部開銷小。TCP首部開銷20字節,UDP開銷8字節。

       其實使用UDP的應用是可以實現可靠數據傳輸的,只是這需要在應用程序自身中建立可靠性機制來完成,即把運輸層的工作放在了應用層進行。

 

       UDP的報文段結構如下:

 

       長度:字段指示了在UDP報文段中的字節數(首部加數據)。

       檢驗和:發送方的UDP對報文段中的所有16比特字的和進行反碼運算,求和時遇到的任何溢出都被回捲。得到的結果就被放在UDP報文段中的檢驗和字段中。在接收方,全部的16比特字(包括檢驗和)加在一起。如果該分組中沒有引入差錯,則在接收方處該和將是1111111111111111。

 

3、TCP

       TCP是面向連接的,一旦建立起一條TCP連接,兩個應用進程之間就可以相互發送數據了。TCP將這些數據引導到該連接的發送緩存(發送緩存是在三次握手初期設置的緩存之一)中,接下來TCP就會不時從發送緩存中取出一塊數據。TCP規範中描述“TCP應該在它方便的時候以報文段的形式發送數據”。TCP可從緩存中取出並放入報文段中的數據數量受限於最大報文段長度(Maximum Segment Size,MSS)。MSS通常根據最初確定的由本地發送的最大鏈路層幀長度(即所謂的最大傳輸單元(Maximum Transmission Unit,MTU))來設置。以太網和PPP鏈路層協議都具有1500字節的MTU,因此MSS的典型值爲1460字節。

 

       TCP報文段結構如下:

 

       其中檢驗和與UDP一樣,6比特的標誌字段意義中,ACK比特用於指示確認字段中的值是有效的。RST、SYN、和FIN比特用於連接建立和拆除。PSH比特指示接收方應立即將數據交給上層。URG比特用於指示報文段中存在着被髮送端的上層設置爲“緊急”的數據。緊急數據的最後一個字節由16比特的緊急數據指針字段指出。(實踐中,PSH、URG和緊急數據指針並沒有使用)。

  • 序號與確認號

       一個報文段的序號是該報文段首字節的字節流編號,假定數據流由一個包含500000字節的文件組成,其MSS爲1000字節,數據流的首字節編號是0,該TCP將爲該數據流構建500各報文段。給第一個報文段分配序號0,第二個報文段分配序號1000,第三個報文段分配序號2000,以此類推。

       而確認號是當前主機期望從通信主機收到的下一字節的序號。

       再舉一個例子,假設主機A已收到一個來自主機B的包含字節0~535的報文段,以及另一個包含字節900~1000的報文段。由於某種原因,主機A還沒有收到字節536~899的報文段。在這個例子中,主機A仍在等待字節536,因此,A到B的下一個報文段將在確認號字段中包含536。因此,TCP被稱爲提供累計確認。

 

  • 往返時間的估計與超時

       在如TCP這樣的實際協議中實現超時/重傳機制時還是會產生許多微妙的問題的。其中最明顯的一個問題就是超時間隔長度的設置。顯然,超時間隔必須大於該連接的往返時間(RTT),即從一個報文段發出到它被確認的時間。

       報文段的樣本RTT(表示爲SampleRTT)就是從某報文段被髮出(即交給IP)到該報文段的確認被收到之間的時間量。大多數TCP的實現僅在某個時刻做一次SampleRTT測量,TCP維持一個SampleRTT均值(稱爲EstimatedRTT)。一旦獲得一個新的SampleRTT時,TCP就會根據公式更新EstimatedRTT。除了估算RTT外,測量RTT的變化也是有價值的。RTT偏差DevRTT用於估算SampleRTT一般會偏離EstimatedRTT的程度。

       顯而易見,超時間隔應該等於EstimatedRTT加一個餘量,所以當SampleRTT值波動較大時,餘量應該大些,波動較小時,餘量應該小些,這時DevRTT就發揮作用了,一般TimeoutInterval = EstimatedRTT + 4 * DevRTT。

       TCP中,每當超時時間發生時,TCP重傳具有最小序號的還未被確認的報文段。只是每次TCP重傳時都會將下一次的超時間隔設爲先前值的兩倍,而不是用從EstimatedRTT和DevRTT推算出的值。然而,每當定時器在另兩個時間(即受到上層應用的數據和收到ACK)中的任意一個啓動時,TimeoutInterval由最近的EstimatedRTT值與DevRTT值推算得到。

 

  • 快速重傳

       一旦收到3個冗餘ACK(總共收到4個),TCP就執行快速重傳,即在該報文段的定時器過期之前重傳丟失的報文段。

       那麼,TCP確認是累積式的,它是否是一個GBN(回退N步,重新從超時的報文段開始發送)協議呢,答案是否定的,許多TCP實現會將正確接收但失序的報文段緩存起來。

 

  • 流量控制

       TCP爲它的應用程序提供了流量控制服務,以消除發送方使接收方緩存溢出的可能性。

       TCP通過讓發送方維護一個稱爲接收窗口(報文段中的窗口)的變量來提供流量控制。接收窗口用rwnd表示,根據接收方緩存可用空間的數量來設置:

       rwnd = RcvBuffer - (LastByteRcvd - LastByteRead)

       發送方則跟蹤LastByteSent - LastByteAcked的值,即發送方發送到連接中但未被確認的數據量。通過將未確認的數據量控制在值rwnd以內,就可以保證接收方的接收緩存不會溢出。

       特殊地,當接收主機的接收窗口爲0時,發送主機繼續發送只有一個字節數據的報文段。這些報文段將會被接收方確認,最終緩存開始清空,並且確認報文中將包含一個非0的rwnd值。

 

  • TCP的連接與關閉

       建立一條TCP連接流程如下:

  • 客戶端的TCP向服務器端的TCP發送一個特殊的TCP報文段。該報文段中不包含應用層數據。但是在報文段的首部中的SYN標誌位被置爲1。另外,客戶回隨機地選擇一個初始序號(client_isn)放在序號字段中。
  • 服務器爲該TCP連接分配TCP緩存和變量,並向該客戶TCP發送允許連接的報文段,這個報文段也不包含應用層數據,但是SYN被置爲1,確認號字段被置爲client_isn + 1,並選擇一個初始序號。
  • 客戶也爲該連接分配緩存和變量,然後向服務器再發送一個報文段,該報文段可以在報文段負載中攜帶客戶到服務器的數據。

 

       爲什麼不使用兩次握手呢?

       因爲若服務器發送的SYNACK報文段沒有成功發送到客戶機,對服務器來說,一個連接已建立起來,會一直等客戶機發消息,而對客戶機來說,並沒有建立這個連接,此時服務器資源就被浪費。

 

關閉一條TCP連接流程如下:

  1. 客戶機發送一個FIN標誌位被置爲1的報文段。
  2. 服務器回送一個確認報文段。
  3. 服務器發送它自己的終止報文段,FIN標誌位被置爲1。
  4. 客戶對這個服務器的終止報文段進行確認。

  • SYN洪泛攻擊

       攻擊者發送大量的SYN報文段,而不完成第三次握手的步驟。隨着這種SYN報文段紛至沓來,服務器不斷爲這些半開連接分配資源,導致服務器的連接資源被消耗殆盡。現在有一種有效的防禦系統,稱爲SYN cookie。

  1. 當服務器收到一個SYN報文段時,服務器不會爲該報文段生成一個半開連接。相反,服務器生成一個初始TCP序列號,該序列號是SYN報文段的源和目的IP地址與端口號通過僅有服務器知道的哈希函數算得。重要的是,服務器並不記憶該cookie或任何對應與SYN的其它狀態信息。(之前三次握手講的方法分配了緩存和變量,即記錄了狀態信息)
  2. 如果客戶是合法的,那麼它將返回一個ACK報文段,當服務器收到ACK,需要驗證該ACK是否與前面發送的某些SYN相對應(之前三次握手講的方法分配了緩存和變量所以不需要驗證)。做法是將SYNACK報文段中的源和目的地IP地址與端口號執行同樣的哈希函數,如果結果+1與SYNACK報文段中的確認號相同的話,則認爲該ACK對應於較早的SYN報文段,因此它是合法的,生成一個具有套接字的全開的連接。

 

  • TCP擁塞控制

       TCP必須使用端到端擁塞控制而不是網絡輔助的擁塞控制。運行在發送方的TCP擁塞控制機制跟蹤一個額外的變量,即擁塞窗口,使用cwnd表示。在一個發送方中未被確認的數據量不會超過cwnd和rwnd中的最小值,即LastByteSent - LastByteAcked <= min{cwnd,rwnd}。

       那麼,爲什麼擁塞窗口可以表示發送速率呢,因爲在每個RRT的起始點,上面的限制條件允許發送方向該連接發送cwnd個字節的數據,在RRT結束時發送方接收對數據的確認報文,因此發送速率大概是cwnd/RTT字節/秒。

       那麼,一個TCP連接怎麼感知路徑上是否擁塞呢?一個丟包事件(超時或收到3個冗餘ACK)意味着擁塞,一個確認報文段意味着通暢。

       TCP擁塞控制算法包括慢啓動,擁塞避免和快速恢復(注意別和快速重傳搞混了)。

  • 慢啓動

當一條TCP連接開始時,cwnd值通常初始值爲一個MSS。然後每收到一個確認報文將cwnd增加一個MSS,這一過程每過一個RTT發送速率就翻倍,呈指數增長。

何時終止慢啓動呢?

  1. 超時:慢啓動閾值ssthresh設置爲cwnd/2,cwnd設爲1,重新開始慢啓動。
  2. cwnd等於ssthresh時:轉移到擁塞避免模式。
  3. 檢測到3個冗餘ACK:執行快速重傳,進入快速恢復狀態。

 

  • 擁塞避免

每個RTT只將cwnd增加一個MSS。

何時終止擁塞避免呢?

  1. 超時:慢啓動閾值ssthresh設置爲cwnd/2,cwnd設爲1,重新開始慢啓動。
  2. 檢測到3個冗餘ACK:慢啓動閾值ssthresh設置爲cwnd/2,cwnd值減半(算上收到的3個冗餘ACK,所以加上3個MSS),執行快速重傳,進入快速恢復狀態。

 

  • 快速恢復

對於引起TCP進入快速恢復狀態的缺失報文段,對每個冗餘ACK,cwnd的值增加一個MSS。

何時終止快速恢復呢?

  1. 丟失報文段的一個ACK到達時:cwnd=ssthresh,進入擁塞避免狀態。
  2. 超時:慢啓動閾值ssthresh設置爲cwnd/2,cwnd設爲1,重新開始慢啓動。

 

參考文章:《計算機網絡自頂向下方法》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章