天天看點

tcp與udp概念與差別

tcp與udp:

tcp:傳輸控制協定,是一種面向連接配接、可靠的、基于位元組留的傳輸層協定。

udp:使用者資料報協定。

ip:網絡之間的互聯協定。

tcp:

1.是面向連接配接的,有三次握手和四次揮手。

2.面向位元組流的,tcp把資料看成一連串無結構的位元組流。

3.是可靠的服務,通過tcp傳資料,無差錯、不重複、不丢失、順序到達,包是有序号的,保證資料的正确性,不丢包。封包頭裡的序号使tcp資料順序到達。封包頭裡的确認序号保證不丢包,有累計确認和逾時重傳機制,有流量控制及擁塞控制的機制。

4、是點對點的連接配接。

5、首部開銷需要20位元組。

6、tcp邏輯通信是全雙工的可靠信道。

7、适用于傳輸資料穩定可靠,适用于網絡通信品質要求較高的場景,需要準确無誤的傳給對方,比如傳輸檔案、發的郵件、遊覽網頁等。

udp還有一個非常重要的應用場景,就是隧道網絡(比如我們常用的VPN,以及在SDN中用到的VXLAN。

udp:(傳輸穩定性上要弱于tcp)

1、發送資料前不需要建立連接配接。

2、面向封包的,沒有擁塞控制,是以網絡出現擁塞不會使源主機的發送速率降低(對實時應用很有用,如ip電話、實時視訊會議等)

3、盡最大努力傳遞,不保證可靠傳遞,資料發送出去就不管了,可能丢包。

4、支援一對一,一對多,多對一和多對多的互動通信。

5、首部開銷小,隻有8位元組(除了源和目标端口,隻有包長度和校驗和),性能損耗小,記憶體資源占用也遠遠小于tcp。

6、是不可靠信道。

7、速度快,可能會丢包,是以适用于對實時性要求較高、但是對少量丢包并沒有太大要求的場景,比如域名查詢、語音通話、視訊直播等。

udp標頭:

除了端口号,基本沒有了(隻有長度、校驗和)

typedef struct _UDP_HEADER 
{
 unsigned short m_usSourPort;       // 源端口号16bit
 unsigned short m_usDestPort;       // 目的端口号16bit
 unsigned short m_usLength;        // 資料包長度16bit
 unsigned short m_usCheckSum;      // 校驗和16bit
}__
           

udp應用場景:

需要資源少,對丢包不敏感不需要一對一建立連接配接,而是可以廣播的形式。需要處理速度快,即使網絡擁塞也不退縮。如:直播、實時遊戲、物聯網。

tcp的標頭:

1、源端口和目标端口是不可少的,是占2個位元組的16位數字。

2、接下來是包的序号。主要是為了解決亂序問題。不編好号怎麼知道哪個先來,哪個後到。序号是 32bit 的無符号數,占4個位元組。

3、确認序号。發出去的包應該有确認,這樣能知道對方是否收到,如果沒收到就應該重新發送,這個解決的是不丢包的問題,也是4個位元組

4、Offset:報頭長度,4位,給出報頭中 32bit 字的數目。需要這個值是因為任選字段的長度是可變的。這個字段占 4bit , 即TCP 最多有 60(15*4) 位元組的首部

5、Resrvd:保留區域,6位,保留給将來使用,目前必須置為 0。

6、狀态位:占6位,SYN 是發起一個連結,ACK 是回複,RST 是重新連接配接,FIN 是結束連接配接。因為 TCP 是面向連接配接的,是以需要雙方維護連接配接的狀态,這些狀态位的包會引起雙方的狀态變更

**URG**:為 1 表示緊急指針有效,為 0 則忽略緊急指針值

**ACK**:為 1 表示确認号有效,為 0 表示封包中不包含确認資訊,忽略确認号字段

**PSH**:為 1 表示是帶有 PUSH 标志的資料,訓示接收方應該盡快将這個封包段交給應用層而不用等待緩沖區裝滿

**RST**:用于複位由于主機崩潰或其他原因而出現錯誤的連接配接。它還可以用于拒絕非法的封包段和拒絕連接配接請求。一般情況下,如果收到一個 RST 為 1 的封包,那麼一定發生了某些問題

**SYN**:同步序号,為 1 表示連接配接請求,用于建立連接配接和使順序号同步( synchronize )

**FIN**:用于釋放連接配接,為 1 表示發送方已經沒有資料發送了,即關閉本方資料流
           

7、視窗大小,TCP 要做流量控制,需要通信雙方各聲明一個視窗,辨別自己目前的處理能力。其占2個位元組,表示從确認号開始,本封包的源方可以接收的位元組數,即源方接收視窗大小。視窗大小是一個 16bit 字段,因而視窗大小最大為 65535(2^16 - 1)。

8、Checksum:校驗和,2個位元組,對整個的 TCP 封包段**(包括 TCP 頭部和 TCP 資料)**,以 16 位字進行計算所得。這是一個強制性的字段,要求由發送端計算和存儲,并由接收端進行驗證。

9、Urgent Pointer:緊急指針,2個位元組,是一個正的偏移量,和順序号字段中的值相加表示緊急資料最後一個位元組的序号。 TCP 的緊急方式是發送端向另一端發送緊急資料的一種方式。 隻有當URG 标志置 1 時緊急指針才有效。

10、Option and Pad:選項和填充,n*4位元組,常見的可選字段是最長封包大小 MSS(Maximum Segment Size) 。每個連接配接方通常都在通信的第一個封包段(為建立連接配接而設定 SYN 标志的那個段)中指明這個選項,它指明本端所能接收的最大長度的封包段。選項長度不一定是 32 位字的整數倍,是以要加填充位,使得報頭長度成為整字數。

11、Data:資料,不定長度,為上層協定封裝好的資料

最大封包段長度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+TCPHeader
通信雙方最終的MSS值=較小MTU-IP Header-TCP Header
           
tcp與udp概念與差別
tcp與udp概念與差別
typedef struct _TCP_HEADER 
{
 short m_sSourPort;              // 源端口号16bit
 short m_sDestPort;              // 目的端口号16bit
 unsigned int m_uiSequNum;         // 序列号32bit
 unsigned int m_uiAcknowledgeNum;  // 确認号32bit
 short m_sHeaderLenAndFlag;        // 前4位:TCP頭長度;中6位:保留;後6位:标志位
 short m_sWindowSize;            // 視窗大小16bit
 short m_sCheckSum;              // 檢驗和16bit
 short m_surgentPointer;           // 緊急資料偏移量16bit
}__attribute__((packed))TCP_HEADER, *PTCP_HEADER;
           

三次握手:(建立連接配接的過程)

1:用戶端主動發起SYN的連接配接請求封包,之後處于SYN-SENT的狀态。(詢問下,能否與你建立連接配接)

2:服務端收到發起的連接配接後,傳回SYN,并且ACK(确認)用戶端的SYN,之後處于syn-rcvd狀态。(傳回syn+ack包)

3:用戶端收到第二步的消息後,将syn-sent狀态改為ESTABLISHED(已連接配接),向服務端回複ACK消息,client向server的通道建立成功。服務端收到ACK消息後,狀态改為ESTABLISHED(已連接配接)狀态,此時server發向client的通道連接配接建立成功。

為什麼要三次握手:

如果網絡不順暢,客戶方第一次發送的連接配接請求沒有及時到達服務端的話,會再次發生連接配接請求,建立連接配接後,第一次滞留的請求包又送達到服務端,而這次服務端會誤認為是第二次發的新連接配接請求,這會造成服務端認為是兩個連結,用戶端認為是一個連結的錯誤。

三次握手本質上來說,為了解決網絡信道不可靠問題,即:為了在不可靠的信道上建立可靠的連接配接。

一包資料可能拆成多包發送,如何解決丢包問題,這些包到達順序不同,如何解決亂序問題:

1、tcp為每個連接配接建立發送緩沖區,從建立連接配接後的第一個位元組序列号為0開始,後面每個位元組加一。

2、發送資料時,從發送緩沖區取一部分資料,組成發送封包,tcp協定頭中會附帶序列号好長度(發送封包=序列号+長度+資料内容)

3、接收端收到封包後要回複确認,确認封包中的ACK=接收序列号加長度(要發送的下一包的起始序列号),這樣一問一答的方式,使發送端能夠确認發送的資料已經被對方收到。

4、發送端也可以一次性發送連續的多包數

據,接收端隻需要回複一次ACK就行了,這樣發送端可以把待發送的資料分割成一系列的碎片,發送到對端,對端根據序列号跟長度,在接收後建構完整的資料,假設其中丢失某些資料包,接收端可以要求發送端重傳(比如丢失了100到199之間資料,接收端向發送端發送ack=100的封包,發送端收到後會重傳這一包的資料,接收端收到後會進行補齊),以上過程不區分客服端和服務端,tcp連接配接是全雙工的。

四次揮手:(用戶端、服務端都可以發起)

1:假設client發起中斷請求,client發送FIN封包。自己進入終止等待1狀态(FIN-WAIT-1)。

2:server收到FIN封包後,回複ACK,告訴用戶端:請求收到了,但我還沒準備好,請繼續等我的消息,這時用戶端進入FIN_WAIT-2狀态,服務端進入close-wait狀态,此時服務端還可以再發送資料,用戶端還可以再接收資料。

3:當server資料發送完成後,向client發送FIN封包,告訴其:我這邊資料發送完了,準備好關閉連接配接了,服務端進入last-Ack狀态。

4:client收到fin後,知道可以關閉連接配接了,但他不相信網絡,怕server不知道要關閉,是以要發生ACK後,進入逾時等待time_wait狀态,經過逾時時間後關閉連接配接。服務端收到ACK後,立即斷開連接配接,狀态為Closed。(client等待2MSL後沒有收到回複,證明server已經正常關閉,那它也可以關閉連接配接了,狀态改為closed,這樣tcp連接配接就關閉了)。

為什麼用戶端要等待逾時時間:

這是為了保證對方收到Ack包,假設用戶端發送完最後一包Ack包就立即釋放連接配接,一旦Ack包在網絡中丢失,服務費一直停留在最後确認狀态,如果用戶端發送完最後一個Ack包後,等待一段時間,這時如果服務端沒有收到Ack包,會重發fin包,用戶端會相應這個FIN包,重發Ack包并重新整理逾時時間。

這個機制跟三次握手一樣,也是為了保證在不可靠的網絡鍊路中,進行可靠的連接配接斷開。

繼續閱讀