TCP/UDP協議詳解...

本文主要講的是傳輸層的兩大重要協議TCP和UDP,雖然在Android開發中,並不須要瞭解到這麼底層,但有理論的支撐,寫代碼老是很自信的啦。理論指導着實踐,實踐是理論檢驗的惟一標準。站在巨人的肩膀窺伺網絡世界。git

用戶數據報協議UDP

用戶數據報協議UDP只在IP的數據報服務至上增長了複用和分用的功能以及差錯檢測的功能。只有面向無鏈接的報文,不可靠傳輸的特色。UDP對應用層交下來的數據只添加首部,並進行特別的處理,就交給網絡層;對網絡層傳遞上來的用戶數據報拆封首部後,原封不動的交給應用層。github

一、UDP的首部格式

用戶數據報UDP分爲兩個字段:數據字段和首部字段,從圖來分析用戶數據報UDP的首部格式。 算法

UDP首部字段很簡單,由4個字段組成,每一個字段的長度都是兩個字節,共8字節。

  • 源端口 原端口號,在須要對方回信時選用,不須要時可全0
  • 目的端口 目的端口號,這在終點交付報文時必須使用,否則數據交給誰呢?
  • 長度 UDP的長度,最小值爲8字節,僅有首部
  • 檢驗和 檢測用戶數據報在傳輸過程是否有錯,有錯就丟棄。

在傳輸的過程當中,若是接收方UDP發現收到的報文中的目的端口不存在,會直接丟棄,而後由網際控制報文協議ICMP給發送方發送「端口不可達」差錯報文。緩存

二、僞首部

計算校驗和時,須要在UDP以前增長12個字節的僞首部。這種首部並非用戶數據報的真正首部。僞首部並不在網絡中傳輸,只是在計算檢驗和,臨時添加在UDP用戶數據報前,獲得一個臨時的用戶數據報。網絡

UDP的校驗和是把首部和數據部分一塊兒校驗,發送方計算校驗和的通常步驟:性能

  1. 將首部的校驗和字段填充爲0(零)
  2. 把僞首部和用戶數據報UDP看出16位的字符串鏈接起來
  3. 若是數據部分不是偶數字節,則填充一個全零字節(該字節不發送到網絡層)
  4. 按二進制反馬計算出這些16位字的和
  5. 而後將和寫入校驗和字段,就能夠發送到網絡層了。

接收方收到用戶數據報後,連同僞首部一塊兒,按二進制反碼求這些16位字的和,無差錯結果是應全爲1.不然出錯,直接丟棄該報文。線程

TCP協議

TCP協議做爲傳輸層主要協議之一,具備面向鏈接,端到端,可靠的全雙工通訊,面向字節流的數據傳輸協議。3d

一、TCP報文段

雖然TCP面向字節流,但TCP傳輸的數據單元倒是報文段。TCP報文段分爲TCP首部和數據部分,TCP報文段首部的前20個字節是固定的,後面有4*n字節根據須要動態添加的選項,最大長度爲40字節。 指針

  • 源端口和目的端口 各佔兩個字節,TCP的分用功能也是經過端口實現的。
  • 序號 佔4個字節,範圍是[0,232],TCP是面向字節流的,每一個字節都是按順序編號。例如一個報文段,序號字段是201,攜帶數據長度是100,那麼第一個數據的序號就是201,最後一個就是300。當達到最大範圍,又從0開始。
  • 確認號 佔4個字節,是指望收到對方下一個報文段的第一個字節的序號。若確認號=N,則表示序號N前全部的數據已經正確收到了。
  • 數據偏移 佔4位,表示報文段的數據部分的起始位置,距離整個報文段的起始位置的距離。間接的指出首部的長度。
  • 保留 佔6位,保留使用,目前爲0.
  • URG(緊急) 當URG=1,代表緊急指針字段有效,該報文段有緊急數據,應儘快發送。
  • ACK(確認) 僅當ACK=1時,確認號纔有效,鏈接創建後,全部的報文段ACK都爲1。
  • PSH(推送) 接收方接收到PSH=1的報文段,會盡快交付接收應用常常,再也不等待整個緩存填滿再交付。實際較少使用。
  • RST(復位) RST=1時,代表TCP鏈接中出現嚴重差錯,必須是否鏈接,再重連。
  • SYN(同步) 在創建鏈接時用來同步序號。當SYN=1,ACK=0,則代表是一個鏈接請求報文段。SYN=1,ACK=1則表示對方贊成鏈接。TCP創建鏈接用到。
  • FIN(終止) 用來釋放一個鏈接窗口。當FIN=1時,代表此報文段的發送方再也不發送數據,請求釋放單向鏈接。TCP斷開鏈接用到。
  • 窗口 佔2個字節,表示發送方本身的接收窗口,窗口值用來告訴對方容許發送的數據量。
  • 校驗和 佔2字節,檢驗和字段查驗範圍包括首部和數據部分。
  • 緊急指針 佔2字節,URG=1時,緊急指針指出本報文段中的緊急數據的字節數(緊急字節數結束後爲普通字節)。
  • 選項 長度可變,最長可達40字節。例如最大報文段長度MSS。MSS指的是數據部分的長度而不是整個TCP報文段長度,MSS默認爲536字節長。窗口擴大,時間戳選項等。

二、TCP創建鏈接-三次握手

三次握手圖例以下,與文字解釋配合使用效果更佳。code

第一次:客戶端發送鏈接請求報文給服務端,其中SYN=1,seq=x。發送完畢後進入SYN_END狀態。

第二次:服務端接收到報文後,發回確認報文,其中ACK=1,ack=x+1,由於須要客戶端確認,因此報文中也有SYN=1,seq=y的信息。發送完後進入SYN_RCVD狀態。

第三次:客戶端接收到報文後,發送確認報文,其中ACK=1,ack=y+1。發送完客戶端進入ESTABLISHED狀態,服務端接收到報文後,進入ESTABLISHED狀態。到此,鏈接創建完成。

三次握手緣由

避免資源被浪費掉。若是在第二步握手時,因爲網絡延遲致使確認包不能及時到達客戶端,那麼客戶端會認爲第一次握手失敗,再次發送鏈接請求,服務端收到後再次發送確認包。在這種狀況下,服務端已經建立了兩次鏈接,等待兩個客戶端發送數據,而實際卻只有一個客戶端發送數據。

三、TCP斷開鏈接-四次揮手

四次揮手指客戶端和服務端各發送一次請求終止鏈接的報文,同時雙方響應彼此的請求。 四次揮手圖例以下,請配置文字解釋使用哦。

四次揮手圖例
第一次揮手:客戶端發送FIN=1,seq=x的包給服務端,表示本身沒有數據要進行傳輸,單面鏈接傳輸要關閉。發送完後,客戶端進入 FIN_WAIT_1狀態。

第二次揮手:服務端收到請求包後,發回ACK=1,ack=x+1的確認包,表示確認斷開鏈接。服務端進入CLOSE_WAIT狀態。客戶端收到該包後,進入FIN_WAIT_2狀態。此時客戶端到服務端的數據鏈接已斷開。

第三次揮手:服務端發送FIN=1,seq=y的包給客戶端,表示本身沒有數據要給客戶端了。發送完後進入LAST_ACK狀態,等待客戶端的確認包。

第四次揮手:客戶端收到請求包後,發送ACK=1,ack=y+1的確認包給服務端,並進入TIME_WAIT狀態,有可能要重傳確認包。服務端收到確認包後,進入CLOSED狀態,服務端到客戶端的鏈接已斷開。客戶端等到一段時間後也會進入CLOSED狀態。

四次揮手緣由 因爲TCP的鏈接是全雙工,雙方均可以主動傳輸數據,一方的斷開須要告知對方,讓對方能夠相關操做,負責任的表現。

使用TCP協議有:FTP(文件傳輸協議)、Telnet(遠程登陸協議)、SMTP(簡單郵件傳輸協議)、POP3(和SMTP相對,用於接收郵件)、HTTP協議等

四、TCP流量控制

滑動窗口協議

TCP滑動窗口協議主要爲了解決在網絡傳輸數據的過程當中,發送方和接收方傳輸數據速率不一致的問題,從而保證數據傳輸的可靠性,達到流量控制的效果。 發送方中的數據分爲三種:

  • 發送已確認
  • 發送未確認
  • 未發送

接收方數據分爲三種:

  • 已接收和確認但未被上層讀取
  • 接收未確認

在發送方的滑動窗口中,可分爲發送窗口和可用窗口。發送窗口中的數據已發送接收方,但未接到接收方的確認;可用窗口則表示發送方還能夠發送多少數據。發送方的窗口大小會受到接收方窗口的改變而改變。

利用滑動窗口機制能有效的控制發送方的發送數據速率。下面是個栗子:
TCP的窗口單位是字節,不是報文端,因此上文假設一個報文包含100個字節。ACK是確認位,ack是確認號,seq是序列號,對應報文的數據格式的。A和B在TCP三次握手時候,B會告訴A本身的接收窗口rwnd大小。上圖中,A向B先發送了三次數據,但第三次丟失了,同時受到B的流量控制,當前ack=201,還需容許繼續發送序號爲201到500共300個字節。當A發送到序號爲500時,就不能發新的數據了,但能接收第三次丟失的數據。

接收方數據被上層讀取後,又能夠接收序號爲501-600共100個字節,因此通知A,接收窗口大小爲100,序號爲501開頭....在上圖的整個過程當中,A共收到B三次流量控制。

TCP報文段發送的機制

應用層把數據傳遞給傳輸層的TCP的發送緩存後,TCP經過不一樣的機制來控制報文段的發送時機。 主要有下面三種機制:

  • TCP維護一個變量,等於最大報文段長度MSS,緩存中存放的數據達到MSS字節時,則以一個報文段發送出去。
  • 發送應用層指明要求的報文段,即TCP支持的推送操做。
  • 發送法計時器期限到了,就要把前面緩存的數據以報文段發送出去,前提是長度不能超過MSS。

TCP傳輸效率問題

不一樣的發送機制都會帶來必定的效率問題,例如用戶發送一個字符,加上20字節首部,獲得21字節長的TCP報文段,再加上21字節的IP首部,就變成41字節長的IP數據報。發送一個字節,線路上就須要發送41字節長的IP數據報,若等待接收方確認,線程就又多了40字節長的數據報。因此在線程帶寬不富裕時,這種傳輸效率很是不高。所以應當推遲發回確認報文,並儘可能使用捎帶確認的方法。

Negle算法

Negle算法主要爲了解決TCP的傳輸效率問題。Negle算法規定:若要把發送的數據逐個字節緩存起來,則發送方須要把第一個字節發送出去,而後緩存後面的字節,在收到接收方第一個字節的確認,再將現有緩存中全部字節組成一個報文段發送出去,繼續緩存後續數據。只有在收到前一個報文的確認以後發送後面的數據。這是爲了減小所用帶寬。當發送數據到達TCP發送窗口的一半或已達到報文段的最大長度也會當即發送報文段,而不是等待接收方確認。這是爲了提升網絡吞吐量。

糊塗窗口綜合徵

TCP接收方的緩存已滿,若上層一次從緩存中讀取一個字節,這樣接收方就能夠繼續接納一個字節的窗口,而後向發送方發送確認,把窗口設爲1個字節(上文所講,IP數據報爲41字節長)。若是這樣持續下去,那麼網絡效率很是低。

因此有效的解決方法,就是讓接收方等待必定時間,讓緩存空間可以接納一個最長的報文段,或者等待接收緩存已有一半的空閒空間,再發出確認報文和通知當前窗口大小。

五、TCP的擁塞控制

擁塞

什麼是擁塞呢,在某段時間,若對網絡中某一資源的需求超過了該資源所能提供的可用部分,網絡性能就會變壞了,這種狀況就叫擁塞。網絡資源常指網絡鏈路容量(帶寬)、交換結點中的緩存和交換處理機。

當出現擁塞,條件容許通常都是經過添加網絡資源,例如帶寬換成更大的,但這治標不治本,並且不必定老是有用。網絡擁塞每每是有許多因素引發的,所以就須要擁塞控制了。

擁塞控制

擁塞控制指防止過多的的數據注入到網絡中,這樣可使網絡中的路由器或鏈路不過載。擁塞機制是一個全局性的過程,涉及到全部主機、全部路由器,以及與下降網絡傳輸性能有光的全部因素。

而滑動窗口協議的流量控制,是指點到點的通訊量控制,是端到端的問題。

TCP的擁塞控制方法

TCP進行擁塞控制的算法有四種:慢開始、擁塞避免、快重傳、快恢復

擁塞控制是基於擁塞窗口的,發送方維持一個擁塞窗口 cwnd的狀態變量。窗口大小取決網絡的擁塞程度,而且動態變化,發送方會讓本身的發送窗口等於擁塞窗口。判斷網絡擁塞的依據就是發送方接收接收方的確認報文是否超時

一、慢開始算法

慢開始指主機由小到大逐漸增大發送窗口,即增大擁塞窗口的數值。初始擁塞窗口cwnd設置爲不超過2到4個最大報文段SMSS的數值,具體規定:

  • 若SMSS≤1095字節,cwnd=4 x SMSS字節,不得超過4個報文段。
  • 若SMSS>1095且≤2190字節,cwnd=3 X SMSS字節,不得超過3個報文段。
  • 若SMSS>2190字節,則 cwnd=2 x SMSS字節,不得超過2個報文段。

從上面的規定限制了初始擁塞窗口的大小。

慢開始在每收到一個對新的報文段的確認後,cwnd就能夠增長最多一個SMSS的數值。

N是剛收到確認的報文段所確認的字節數,當N<SMSS時,擁塞窗口每次的增長量要小於SMSS。下文舉例說明慢開始的原理(實際上,TCP的窗口是以字節大小爲單位,下文爲了方便以報文端形容):

從圖可知,初始化窗口未1,全部發送M1報文段,收到確認號以後,發送M2-M3兩個報文段,由於擁塞窗口增大了,後面的輪次也是這樣翻倍增長的。隨着輪次的增多,那麼發送到網絡的數據就會急劇增長,容易出現擁塞,所以須要慢開始門限(ssthresh)狀態變量。

  • 當cwnd<ssthresh時,使用慢開始算法
  • 當cwnd>ssthresh時,使用擁塞避免算法
  • 當cwnd=ssthresh時,慢開始或者擁塞避免算法
二、擁塞避免算法

擁塞避免算法就是讓cwnd緩慢增大,每個輪次把擁cwnd增長1,而不是像慢開始算法那樣翻倍增長。須要注意的是,擁塞避免算法只是讓網絡不那麼快出現擁塞,而不是避免擁塞出現。

上文已經說到,判斷網絡是否擁塞以報文是否超時爲準,當網絡出現擁塞時,會把ssthresh設爲原有的一半,而後開始慢開始算法。以下圖所示:

在上黑色園圈4點的時候,發送方收到對同一個報文端重複確認(3-ACK)。這種狀況,個別報文端會在網絡中丟失,但實際上未發生網絡擁塞,發送方未及時收到確認,就會產生超時,誤認爲出現擁塞,發送方會從新開始慢開始算法。減低了傳輸效率。所以,就須要快重傳算法了。

三、 快重傳算法

快重傳算法是讓發送方今早知道發生了個別報文段的丟失。快重傳算法要求接收方不要等待本身發送數據時才進行捎帶確認,而是當即發送確認。也就是說,但出現丟包狀況,接收方在接收新數據時會重複發送對丟失包的前一個報文段的確認號。發送方接收到三次確認號後,就判斷該丟失報文段確實丟失,會當即進行重傳(快重傳)。

四、快恢復算法

在上文,知道只是報文段丟失,而不是網絡出現擁塞後,發送方會調整ssthresh爲原來的一半,而後繼續進行擁塞避免算法,這個過程就叫快開恢復算法。

五、小結

可見,TCP擁塞控制四個算法是相輔相成,少了誰都不行,共同維護這擁塞控制機制。下面是整體的流程圖。

從流量控制和擁塞控制總體看,涉及到三個窗口,接收窗口、發送窗口、擁塞窗口。發送窗口的數值是不能大於接收窗口的,可是擁塞窗口由網絡的擁塞程度決定的(因此上文的發送窗口等於擁塞窗口,是假設在接收窗口數值足夠大,可以容納擁塞窗口的數據)。所以, 發送窗口的上限值應該是擁塞窗口cwnd和接收窗口rwnd之間的最小值。也就是說,經過流量控制和擁塞控制,發送的發送速率取決於cwnd和rwnd中數值較小的一個。

GitHub

點個贊收藏吧

相關文章
相關標籤/搜索