TCP和UDP

TCP和UDP通訊的特色
不一樣主機上進程與進程之間的數據傳輸,根據數據的大小可分爲兩種可能的情形:mysql

  1. 待發送數據較短,單個數據包便可發送完成
  2. 待發送數據較長,須要劃分紅多個數據包發送

這兩種不一樣的數據傳輸情形,正對應UDP和TCP兩種協議:一個數據包能完成發送的使用UDP協議,分包發送的使用TCP協議。但注意,這裏的劃分方式並不嚴謹,UDP發送的數據並不必定短(無論有多長數據,UDP都會總體原封不動的看成一個包傳輸),TCP發送的數據也並不必定長,之因此如此劃分是爲了稍後方便解釋這兩個協議的特性sql

若是採用分包傳輸的機制,也就是TCP協議,就須要將待發送的數據劃分紅多個數據包來發送,一邊劃分一邊放入TCP套接字的Send Buffer,同時還會對劃分的每一個數據包進行編號,以便校驗數據包的前後順序,同時還能根據序號檢測是否丟失須要重傳數據包。Send Buffer中有了數據包後,就能夠進入下一層網絡層,而後經過網絡發送給目標主機,因此,採用TCP通訊來傳輸數據時,就像水流同樣,數據包從源端的應用層流到目標端,中間的任何一個層次均可能已經有了數據。因此,TCP數據傳輸是數據流模式緩存

由於有不少數據包要發送,因此在劃分數據包以前就須要先在兩端主機之間創建好一個TCP的鏈接,以便讓或許全部的數據包都經過這個鏈接來傳輸,因此TCP通訊是面向鏈接的。既然是面向鏈接的,那麼源端和目標端均可以藉此鏈接來發送數據,因此TCP通訊是雙向的,或者說是全雙工的。既然是雙向通訊,那麼鏈接的每一端都須要有發送者和接收者,一端的發送者發送的數據被另外一端的接收者接收。爲了保證每一端的收、發互不影響,每端都採用兩個TCP套接字的緩存:讀緩存和寫緩存,也成爲發送緩存或接收緩存。某端發送數據時,將劃分的數據包放入Send Buffer,經過網絡發送給目標主機後,放入對方的Recv Buffer,另外一端發送數據也如此網絡

有了鏈接,雙方就能夠根據這個鏈接來作一些控制,協商一些鏈接的屬性,好比一個包最大多少個字節,並且發送方能夠根據鏈接來判斷是否比較阻塞(擁塞)或不太穩定從而調整發送速度,這是擁塞控制。接收方若是發現接收速度或數據處理速度跟不上對方的發送速度,能夠通知對方下降發送速度甚至短暫中止發送oracle

若是待發送數據只想用一個數據包發送,那麼採用UDP傳輸協議。UDP傳輸時不會對數據進行分包,固然也就不須要編號,由於只有一個包,只需發送一次,因此UDP不須要創建鏈接。由於沒有鏈接,因此只能是單向傳輸,且沒法很好的判斷數據包是否到達目標。由於沒有鏈接,也沒法像TCP同樣能夠藉此來作擁塞控制。但也正由於UDP不須要鏈接,不須要分包,因此UDP傳輸效率比TCP要高,且傳輸期間佔用的系統資源也要遠小於TCPssh

UDP協議
UDP(User Datagram Protocol)是用戶數據報協議,是OSI的傳輸層協議。它只是比IP數據包多提供了一些不多功能,好比添加端口標識不一樣的應用層協議、差錯校驗等
UDP的主要特色包括:tcp

  • UDP是無鏈接的,即發送數據以前不須要和對方先創建好鏈接(因此也沒有關閉鏈接的過程),所以效率比較高
  • UDP只能儘可能保證數據能夠到達對方,但沒法保證可靠的交付。主要仍是由於沒有創建鏈接,數據丟失後沒法重傳
  • UDP是面向數據報的。當應用層採用UDP協議時,UDP將數據添加首部後直接給網絡層,它不會合並也不會拆分,而是應用層給多少數據,UDP就包裝多少數據,包裝後的數據稱爲數據報。傳輸時以數據報爲單位,一次傳輸一個數據報文。接收到UDP報文時,UDP解封后直接將整個數據交給應用層。因此,對於使用UDP協議的程序,必須選擇大小合適的報文,若是報文太大,則在IP層會對其進行分片,這會致使IP層的效率極低
  • UDP首部開銷很小,只有8個字節,而TCP的首部有20個字節,相比TCP而言,UDP的效率要高一些
  • UDP沒有擁塞控制,在網絡出現擁塞的時候,源主機不會所以而下降發送速率,因此UDP的實時性比較好,因此,對於容許丟失一些數據,但又要求高實時性的場景,UDP更爲適合
  • 差錯校驗功能有限,在校驗後發現不一致,將直接丟棄數據報

UDP數據報包含兩個部分ide

  • 數據部分:首部部分很是簡單,共8個字節4字段,每一個字段2字節
  • 首部部分
    屏幕快照 2020-07-27 16.56.05TCP和UDP
    屏幕快照 2020-07-27 16.56.52TCP和UDP
    TCP首部
  • 源端口、目標端口:計算機上的進程要和其餘進程通訊是要經過計算機端口的,而一個計算機端口某個時刻只能被一個進程佔用,因此經過指定源端口和目標端口,就能夠知道是哪兩個進程須要通訊。源端口、目標端口是用16位表示的,可推算計算機的端口個數爲2^16個
  • 序列號:表示本報文段所發送數據的第一個字節的編號。在TCP鏈接中所傳送的字節流的每個字節都會按順序編號。因爲序列號由32位表示,因此每2^32個字節,就會出現序列號迴繞,再次從 0 開始
  • 確認號:表示接收方指望收到發送方下一個報文段的第一個字節數據的編號。也就是告訴發送方:我但願你(指發送方)下次發送的數據的第一個字節數據的編號爲此確認號
  • 數據偏移:表示TCP報文段的首部長度,共4位,因爲TCP首部包含一個長度可變的選項部分,須要指定這個TCP報文段到底有多長。它指出 TCP 報文段的數據起始處距離 TCP 報文段的起始處有多遠。該字段的單位是32位(即4個字節爲計算單位),4位二進制最大表示15,因此數據偏移也就是TCP首部最大60字節
  • URG:表示本報文段中發送的數據是否包含緊急數據。後面的緊急指針字段(urgent pointer)只有當URG=1時纔有效
  • ACK:表示是否前面確認號字段是否有效。只有當ACK=1時,前面的確認號字段纔有效。TCP規定,鏈接創建後,ACK必須爲1,帶ACK標誌的TCP報文段稱爲確認報文段
  • PSH:提示接收端應用程序應該當即從TCP接收緩衝區中讀走數據,爲接收後續數據騰出空間。若是爲1,則表示對方應當當即把數據提交給上層應用,而不是緩存起來,若是應用程序不將接收到的數據讀走,就會一直停留在TCP接收緩衝區中
  • RST:若是收到一個RST=1的報文,說明與主機的鏈接出現了嚴重錯誤(如主機崩潰),必須釋放鏈接,而後再從新創建鏈接。或者說明上次發送給主機的數據有問題,主機拒絕響應,帶RST標誌的TCP報文段稱爲復位報文段
  • SYN:在創建鏈接時使用,用來同步序號。當SYN=1,ACK=0時,表示這是一個請求創建鏈接的報文段;當SYN=1,ACK=1時,表示對方贊成創建鏈接。SYN=1,說明這是一個請求創建鏈接或贊成創建鏈接的報文。只有在前兩次握手中SYN才置爲1,帶SYN標誌的TCP報文段稱爲同步報文段
  • FIN:表示通知對方本端要關閉鏈接了,標記數據是否發送完畢。若是FIN=1,即告訴對方:「個人數據已經發送完畢,你能夠釋放鏈接了」,帶FIN標誌的TCP報文段稱爲結束報文段
  • 窗口大小:表示如今容許對方發送的數據量,也就是告訴對方,從本報文段的確認號開始容許對方發送的數據量,達到此值,須要ACK確認後才能再繼續傳送後面數據,由Window size value * Window size scaling factor(此值在三次握手階段TCP選項Window scale協商獲得)得出此值
  • 校驗和:提供額外的可靠性
  • 緊急指針:標記緊急數據在數據字段中的位置
  • 選項部分:其最大長度可根據TCP首部長度進行推算。TCP首部長度用4位表示,選項部分最長爲:(2^4-1)*4-20=40字節

TCP首部常見選項:memcached

  • 最大報文段長度:Maxium Segment Size,MSS,一般1460字節
    • 窗口擴大:Window Scale
    • 時間戳: Timestamps
  • 最大報文段長度MSS(Maximum Segment Size)指明本身指望對方發送TCP報文段時那個數據字段的長度。好比:1460字節。數據字段的長度加上TCP首部的長度纔等於整個TCP報文段的長度。MSS不宜設的太大也不宜設的過小。若選擇過小,極端狀況下,TCP報文段只含有1字節數據,在IP層傳輸的數據報的開銷至少有40字節(包括TCP報文段的首部和IP數據報的首部)。這樣,網絡的利用率就不會超過1/41。若TCP報文段很是長,那麼在IP層傳輸時就有可能要分解成多個短數據報片。在終點要把收到的各個短數據報片裝配成原來的TCP報文段。當傳輸出錯時還要進行重傳,這些也都會使開銷增大。所以MSS應儘量大,只要在IP層傳輸時不須要再分片就行。在鏈接創建過程當中,雙方都把本身可以支持的MSS寫入這一字段。 MSS只出如今SYN報文中。即:MSS出如今SYN=1的報文段中
    • MTU和MSS值的關係:MTU=MSS+IP Header+TCP Header
    • 通訊雙方最終的MSS值=較小MTU-IP Header-TCP Header
  • 窗口擴大
    • 爲了擴大窗口,因爲TCP首部的窗口大小字段長度是16位,因此其表示的最大數是65535。可是隨着時延和帶寬比較大的通訊產生(如衛星通訊),須要更大的窗口來知足性能和吞吐率,因此產生了這個窗口擴大選項
  • 時間戳
    • 能夠用來計算RTT(往返時間),發送方發送TCP報文時,把當前的時間值放入時間戳字段,接收方收到後發送確認報文時,把這個時間戳字段的值複製到確認報文中,當發送方收到確認報文後便可計算出RTT。也能夠用來防止迴繞序號PAWS,也能夠說能夠用來區分相同序列號的不一樣報文。由於序列號用32爲表示,每2^32個序列號就會產生迴繞,那麼使用時間戳字段就很容易區分相同序列號的不一樣報文
      屏幕快照 2020-07-27 17.00.04TCP和UDP
      TCP協議PORT
  • 傳輸層經過port號,肯定應用層協議
  • Port number:
  • tcp:傳輸控制協議,面向鏈接的協議;通訊前須要創建虛擬鏈路;結束後拆除鏈路
    • 0-65535
  • udp:User Datagram Protocol,無鏈接的協議
    • 0-65535
  • IANA:互聯網數字分配機構(負責域名,數字資源,協議分配)
    • 0-1023:系統端口或特權端口(僅管理員可用) ,衆所周知,永久的分配給固定的系統應用使用,22/tcp(ssh), 80/tcp(http), 443/tcp(https)
    • 1024-49151:用戶端口或註冊端口,但要求並不嚴格,分配給程序註冊爲某應用使用,1433/tcp(SqlServer), 1521/tcp(oracle),3306/tcp(mysql),11211/tcp/udp (memcached)
    • 49152-65535:動態端口或私有端口,客戶端程序隨機使用的端口
    • 其範圍的定義:/proc/sys/net/ipv4/ip_local_port_range

可靠傳輸:丟失重傳和窗口滑動
基於TCP鏈接傳輸數據是可靠的,它保證數據不丟失,且能按照正確的順序被對方接收。這裏涉及到一些比較重要的機制,簡單描述下:
首先假設只有一個數據包須要傳輸,若是這個包沒有丟失,也沒有出現差錯,那麼一切都正常,但若是傳輸的這個數據包丟失了或出現差錯了,那麼就要求發送方重傳這個包。爲了可以重傳這個包,發送方須要遵照一些簡單的規則:性能

  1. 保留這個包不能刪除,以便出現問題時直接重傳
  2. 發送這個包後中止,等待接收方回覆確認包
  3. 設置一個定時器,在指定時間內若是沒有收到接收方的回覆,則認爲包丟失,因而重傳該包
  4. 若是收到確認包以後,開始傳輸下一個包

遵照這幾個規則能夠保證基於TCP鏈接傳輸數據是可靠的,不會丟失任何數據,可是這樣的效率很是低下,每次發送數據包都須要等待,因而,改進這種方案,不是一次發送一個包就等待,而是一次性發送多個包,而後進入等待。如今規則改進:

  1. 一次發送4個包(這是假設值),發送後保留4個包,以便出現問題時重傳
  2. 發送4個包後中止,等待接收方恢復確認包
  3. 設置一個定時器,在指定時間內若是沒有收到接收方的回覆,則重傳4個包
  4. 接收方接收到包以後,若是4個包一切正常,則回覆,讓發送方發送後續數據包
  5. 若是接收方發現中間第3個包出現問題,則發送確認,確認號是第3個包的起始字節,也就是說,接收方只接受到了前兩個包,後面兩個包須要重傳
  6. 發送方根據收到的確認號,知道要重傳第三個包,因而將保留下來的4個包中的前兩個剔除,並加入兩個新的包,因而本次再次發送4個包。本次發送的四個包中,前兩個是重傳包,後兩個是新包
  7. 接收方收到新的4個包後,若是一切正常,則確認給發送方
    根據這種規則傳輸數據,比以前每發送一次包就停下來等待,效率要高不少。並且,一次發送多少個包是能夠更改的,這取決於窗口(Window)的大小。假如一個包的大小是100字節,窗口大小是400字節,那麼一次就能發送4個包,若是窗口大小是1000字節,一次就能發送10個包。每次發送一個窗口中的包以後,若是接收到接收方的確認信息,那麼窗口中的全部包都將滑出窗口,並存放新的數據包。若是中間某個包出現了差錯,則只滑出那部分已確認接收的包,並放入對應個數的新數據包

TCP鏈接創建時,接收方會和發送方協商窗口應設置爲多大,這樣發送方就會根據這個窗口大小決定一次發送多少個包。而且,接收方能夠隨時動態調整窗口的大小,從而限制發送方發送數據包的速度,實現流量的控制。這種窗口滑動的模式雖然已經足夠高效了,可是仍不足,好比窗口大小是4個包的大小,接收方發現第二個包出錯了,會致使發送方重傳這4個包中的3個,效率較低,更加的處理方式是隻重傳哪一個出錯的包。這就是改進的傳輸模式,實現方式在接收方回覆確認信息給發送方時,在其回覆包的TCP首部可選字段假如一個選項,來指明已經接收到的字節的起始和接收位置

相關文章
相關標籤/搜索