7、TCP的連接與斷開
7.1、TCP的連接建立
7.1.1、TCP連接建立過程中要解決的3個問題
1.要使一方確定對方的存在。
2.雙方之間協(xié)商一些參數(shù)比如說滑動窗口的大小,時間戳選項等等。
3.能夠?qū)\(yùn)輸實體資源(緩存大小,連接表中的項目)進(jìn)行一些分配。
7.1.2、三次握手建立連接
在建立連接之前,Client處于CLOSED狀態(tài),而Server處于LISTEN的狀態(tài)。
1.第一次握手:客戶端主動給服務(wù)端發(fā)送一個SYN報文,并攜帶自己的初始化序列號一起發(fā)送給服務(wù)端。此時客戶端處于一個SYN_SEND的狀態(tài)。
2.第二次握手:服務(wù)端收到客戶端發(fā)來的SYN報文之后,就會以自己的SYN報文作為應(yīng)答,然后將自己的初始化序列號發(fā)送給客戶端,并且會將客戶端的初始化序列號+1作為自己的ACK值發(fā)送給客戶端,以表示自己已經(jīng)收到了客戶端的SYN報文。此時服務(wù)端處于一個SYN_RECV的狀態(tài)。
3.第三次握手:客戶端收到服務(wù)端發(fā)來的SYN報文之后,會把服務(wù)端的初始化序列號+1作為ACK值發(fā)送給服務(wù)端,用來表示自己已經(jīng)收到了服務(wù)端發(fā)來的SYN報文。此時客戶端處于一個ESTABLISHED的狀態(tài)。
7.1.3、為什么兩次不行
一開始A向B發(fā)出建立連接的請求但是這個報文超時了,A又向B發(fā)送了一個請求連接報文然后通過兩次握手建立連接傳送數(shù)據(jù)最后釋放連接。但是這時候,超時的報文遲到發(fā)送他們又會建立連接然后服務(wù)端等待發(fā)送數(shù)據(jù),但是這時候客戶端已經(jīng)沒有數(shù)據(jù)可發(fā)了。
7.1.4、三次握手的原因
可靠性要求之一(確認(rèn)、序號、重傳):起始數(shù)據(jù)字節(jié)編號協(xié)商
如圖所示它主要是為了起始數(shù)據(jù)字節(jié)編號協(xié)商1是我發(fā)送的報文序號是456,2是我接受到了你下次從457開始發(fā),3是好的我準(zhǔn)備接收124。如果沒有這個3號報文B端就不知道下次從哪開始發(fā)。
7.1.5、三次握手建立TCP連接的各種狀態(tài)
首先服務(wù)端開始處于監(jiān)聽狀態(tài)監(jiān)聽客戶端發(fā)來的請求,客戶端發(fā)送建立連接的請求之后處于SYN-SEND狀態(tài),服務(wù)端發(fā)送確認(rèn)報文之后處于SYN-RCVD狀態(tài),當(dāng)客戶端發(fā)送確認(rèn)報文給服務(wù)端客戶端處于ESTAB-LISHED(連接建立狀態(tài))服務(wù)端接收到報文后進(jìn)入ESTAB-LISHED狀態(tài)。
7.1.6、三次握手可以攜帶數(shù)據(jù)嗎?
大概很多人的正常思維都是在三次握手過程中是不可以攜帶數(shù)據(jù)的,其實不然,在第三次握手的過程中是可以攜帶數(shù)據(jù)滴;換句話說就是,在第一、第二次握手過程中不可以攜帶數(shù)據(jù)的,但是在第三次握手過程中是可以攜帶數(shù)據(jù)的。
那為什么會這樣呢?大家不妨大膽的猜測猜測....
因為是網(wǎng)絡(luò)連接,就會涉及到網(wǎng)絡(luò)安全的因素;大家想想,如果在第一次握手的時候就可以攜帶數(shù)據(jù),那么要是有人蓄謀已久惡意攻擊服務(wù)器,在第一次握手中的SYN報文注入大量數(shù)據(jù),攻擊者根本就不考慮服務(wù)器的發(fā)送接收能力,然后就瘋狂重復(fù)發(fā)SYN報文,這就會讓服務(wù)器花費(fèi)大量的內(nèi)存和時間去處理這些報文,所以如果在第一次握手就放數(shù)據(jù)的話,就會讓服務(wù)器更加容易受到攻擊。
7.2、TCP連接釋放
1.客戶端向服務(wù)端發(fā)送一個報文FIN為1,序號為u然后進(jìn)入FIN-WAIT1狀態(tài)。
2.服務(wù)端向客戶端發(fā)送確認(rèn)報文序號為v,確認(rèn)序號為u+1然后進(jìn)入CLOSE-WAIT狀態(tài)。
3.客戶端收到服務(wù)端發(fā)回的確認(rèn)報文之后進(jìn)入FIN-WAIT2狀態(tài)此時客戶端連接已經(jīng)關(guān)閉客戶端無法向服務(wù)端傳送數(shù)據(jù)。
4.然后服務(wù)端被動關(guān)閉它向客戶端發(fā)送一個FIN為1的報文段要求釋放服務(wù)端到客戶端的連接。進(jìn)入LAST-ACK等待客戶端發(fā)送最后一個ACK報文。
5.客戶端發(fā)送最后一次揮手確認(rèn)報文然后進(jìn)行closed,服務(wù)端直接CLOSED。
6.客戶端要等待2MSL才CLOSED。
當(dāng)不按套路出牌時返回RST比如上來沒建立連接服務(wù)端給客戶端來一個ACK或FIN。
7.2.1、為什么客戶端要等2MSL才關(guān)閉
1.因為服務(wù)端要保證TCP全雙工通信連接都能正確關(guān)閉,因為如果服務(wù)端沒收到ACK那么就會再發(fā)一次FIN那么客戶端如果關(guān)閉則無法回復(fù)ACKServer就會收到RST而不是ACK。所以為了讓服務(wù)端能正確的收到ACK報文確保連接正確關(guān)閉所以要等一會再關(guān)。
2.一旦客戶端直接進(jìn)入CLOSED很有可能端口號跟之前相同然后上一次連接中有些數(shù)據(jù)滯留在網(wǎng)絡(luò),當(dāng)你再建立連接時這些老的數(shù)據(jù)包會和新的數(shù)據(jù)混淆等待2MSL基本上可以讓這些老數(shù)據(jù)消失。
7.2.2、?;钣嫊r器
?當(dāng)建立連接之后一旦斷網(wǎng)了,連接空閑時間達(dá)到兩個小時以上服務(wù)器自動發(fā)送探測報文段,若發(fā)送了10個報文段(每個相隔75秒)還沒有響應(yīng),就假定客戶除了故障,因而終止連接。
?TCP計時器總結(jié):TCP發(fā)送報文計時器,超時重傳計時器,?;钣嫊r器,持續(xù)(0窗口探測計時器),時間等待計時器(2MSL);
7.3、TCP黏包
7.3.1、什么是TCP黏包?
在以往的網(wǎng)絡(luò)基礎(chǔ)學(xué)習(xí)中,可能會客戶端連續(xù)不斷向服務(wù)端發(fā)送數(shù)據(jù)包的時候,服務(wù)端接收的數(shù)據(jù)會出現(xiàn)兩個數(shù)據(jù)包黏在一起的情況。
?TCP是基于字節(jié)流的可靠傳輸,在應(yīng)用層和傳輸層之間的數(shù)據(jù)交互是大小不等的數(shù)據(jù)塊,但是TCP就會將這些數(shù)據(jù)塊看成是一串一串沒有結(jié)構(gòu)的字節(jié)流,并且沒有邊界。
?學(xué)習(xí)TCP結(jié)構(gòu)的時候也可以看出,它的首部沒有表示數(shù)據(jù)長度的字段。
所以,在使用TCP進(jìn)行數(shù)據(jù)傳輸?shù)臅r候,就會有黏包或者拆包的現(xiàn)象發(fā)生。一個數(shù)據(jù)包中包含了發(fā)送端發(fā)送的兩個數(shù)據(jù)包的信息,那么就把這種現(xiàn)象叫做黏包。接收端在收到這兩個數(shù)據(jù)包的時候,要么是不完整的,要么是多出來一塊,這種情況就是發(fā)生了黏包和拆包。
7.3.2、TCP黏包是怎么產(chǎn)生的?
1.發(fā)送方產(chǎn)生黏包
因為在采用TCP傳輸數(shù)據(jù)的客戶端和服務(wù)端是保持一個長鏈接的狀態(tài),雙方在不斷開的狀態(tài)下,是可以一直傳輸數(shù)據(jù)的。如果發(fā)送的數(shù)據(jù)包非常小的時候,那么TCP默認(rèn)就會啟用Nagle算法,將這些非常小的數(shù)據(jù)包進(jìn)行合并發(fā)送(這個合并發(fā)送過程就是在發(fā)送緩沖區(qū)中進(jìn)行的),發(fā)出來的數(shù)據(jù)就會是一個黏包的狀態(tài)。
2.接收方產(chǎn)生黏包
數(shù)據(jù)在到達(dá)接收方的時候,是從網(wǎng)絡(luò)模型的下方傳遞至傳輸層,傳輸層的TCP協(xié)議就會將這些數(shù)據(jù)放置到接收緩沖區(qū),然后由應(yīng)用層主動獲取,那么這個時候就會出現(xiàn)在我們程序調(diào)用的讀取數(shù)據(jù)函數(shù)不能及時的把緩沖區(qū)中的數(shù)據(jù)拿出來,下一個數(shù)據(jù)的一部分就又到緩沖區(qū)中,當(dāng)我們讀取的時候就是黏包。
7.3.3、怎么解決黏包和拆包?
1.FixedLengthFrameDecoder
對于使用固定長度的粘包和拆包場景,可以使用FixedLengthFrameDecoder,該解碼器會每次讀取固定長度的消息,如果當(dāng)前讀取到的消息不足指定長度,那么就會等待下一個消息到達(dá)后進(jìn)行補(bǔ)足。
2.LineBasedFrameDecoder與DelimiterBasedFrameDecoder
對于通過分隔符進(jìn)行粘包和拆包問題的處理,Netty提供了兩個編解碼的類,LineBasedFrameDecoder和DelimiterBasedFrameDecoder。這里L(fēng)ineBasedFrameDecoder的作用主要是通過換行符,即\\n或者\(yùn)\r\\n對數(shù)據(jù)進(jìn)行處理;而DelimiterBasedFrameDecoder的作用則是通過用戶指定的分隔符對數(shù)據(jù)進(jìn)行粘包和拆包處理。
3.LengthFieldBasedFrameDecoder與LengthFieldPrepender
這里L(fēng)engthFieldBasedFrameDecoder與LengthFieldPrepender需要配合起來使用,其實本質(zhì)上來講,這兩者一個是解碼,一個是編碼的關(guān)系。它們處理粘拆包的主要思想是在生成的數(shù)據(jù)包中添加一個長度字段,用于記錄當(dāng)前數(shù)據(jù)包的長度。
4.自定義粘包與拆包器
對于粘包與拆包問題,其實前面三種基本上已經(jīng)能夠滿足大多數(shù)情形了,但是對于一些更加復(fù)雜的協(xié)議,可能有一些定制化的需求。對于這些場景,其實本質(zhì)上,我們也不需要手動從頭開始寫一份粘包與拆包處理器,而是通過繼承LengthFieldBasedFrameDecoder和LengthFieldPrepender來實現(xiàn)粘包和拆包的處理。
8、UDP主要特點
1.不需要建立連接。
2.盡最大努力交付。
3.面向報文交付。
4.沒有擁塞控制。
5.支持多種交互通信。
6.首部開銷小僅有8字節(jié)。
7.應(yīng)用程序必須選擇合適的報文如果報文太長則需要IP分片,太小降低效率。
8.1、運(yùn)用場景:
1.可以重復(fù)請求信息的情況下例如:RIP,DNS,DHCP等
2.一次性傳小量數(shù)據(jù)的應(yīng)用
3.實時應(yīng)用
4.多媒體應(yīng)用。
8.2、UDP首部信息
1.源端口(2)
2.目的端口(2)
3.長度(2)
4.檢驗和(2)(首部+偽首部+數(shù)據(jù))
這個檢驗和是交給上層應(yīng)用程序檢查的,它就相當(dāng)于你拆快遞先檢查收貨地址(IP地址),再檢查是不是你的名字(端口),再檢查里面收件是不是錯的(里面的數(shù)據(jù))。
以上就是我對TCP、UDP相關(guān)的總結(jié);如果對您有所幫助的話,那就是我花時間整理這篇文章最大的意義了。
-
緩沖區(qū)
+關(guān)注
關(guān)注
0文章
33瀏覽量
9089 -
TCP
+關(guān)注
關(guān)注
8文章
1347瀏覽量
78933 -
UDP
+關(guān)注
關(guān)注
0文章
322瀏覽量
33849
發(fā)布評論請先 登錄
相關(guān)推薦
評論