網(wǎng)絡(luò)通信-TCP/UDP

參考:
https://blog.csdn.net/zhang6223284/article/details/81414149
https://blog.csdn.net/qq_38950316/article/details/81087809
https://www.cnblogs.com/qdhxhz/p/8470997.html

TCP/IP是個協(xié)議組,可分為三個層次:網(wǎng)絡(luò)層、傳輸層、應(yīng)用層。
網(wǎng)絡(luò)層有:IP協(xié)議、ICMP協(xié)議、ARP協(xié)議、RARP協(xié)議、BOOTP協(xié)議。
傳輸層有:TCP協(xié)議、UDP協(xié)議。
應(yīng)用層有:FTP、HTTP、TELNET、SMTP、DNS等協(xié)議。

TCP,UDP,HTTP

  • TCP是基于TCP協(xié)議實現(xiàn)的網(wǎng)絡(luò)文本協(xié)議,屬于傳輸層
  • UDP是和TCP對等的,屬于傳輸層
  • HTTP本身就是一個協(xié)議,是從Web服務(wù)器傳輸超文本到本地瀏覽器的傳送協(xié)議。基于TCP。

一、TCP

包頭

TCP包頭.jpg
  • 源端口、目標端口必不可少
  • 包的序號:主要用來解決亂序問題
  • 確認序號:發(fā)出去的包應(yīng)該由確認,這樣能知道對方是否收到,如果沒收到就應(yīng)該重新發(fā)送,主要解決丟包問題
  • 狀態(tài)位:SYN是發(fā)起一個鏈接,ACK是回復(fù),RST是重新連接,F(xiàn)IN是結(jié)束連接。TCP是面向連接的,因此需要雙方維護連接的狀態(tài),這些狀態(tài)位的包會引起雙方的狀態(tài)變更
  • 窗口大小:TCP要做流量控制,需要通信雙方各聲明一個窗口,標識自己當前的處理能力

使用TCP協(xié)議的連接建立與斷開,正常過程下至少需要發(fā)送7個包才能完成,就是我們常說的三次握手,四次揮手。

TCP三次握手+四次揮手.png
  • 序列號 Sequeuece number(seq):數(shù)據(jù)包本身的序列號,初始序列號是隨機的。
  • 確認號 Acknowledgment number(ack):在接收端,用來通知發(fā)送端數(shù)據(jù)成功接收。
  • 標志位,標志位只有為 1 的時候才有效:
    SYN(synchronize):同步序列編號,表示在連接建立時用來同步序號。
    ACK(Acknowledgement):確認字符,TCP協(xié)議規(guī)定,只有ACK=1時有效,也規(guī)定連接建立后所有發(fā)送的報文的ACK必須為1。
    FIN(finish):用來釋放一個連接。當FIN=1時,表明此報文段的發(fā)送方的數(shù)據(jù)已經(jīng)發(fā)送完畢,并要求釋放連接。

建立連接:三次握手

一次TCP連接的建立需要三次握手。

TCP三次握手.jpg
  • 第一次握手
    客戶端向服務(wù)端發(fā)送請求報文;即SYN=1,ACK=0,seq=x。建立連接時,客戶端發(fā)送SYN包(syn=j)到服務(wù)端,并進入SYN_SENT狀態(tài),等待服務(wù)器確認;
    A:你好,我是A

  • 第二次握手
    服務(wù)器收到SYN包,必須確認客戶的SYN(ack=j+1),同時自己也發(fā)送一個SYN包(syn=k),即SYN+ACK包,此時服務(wù)器進入SYNC_RECV狀態(tài);
    B:你好,A,我是B

  • 第三次握手
    客戶端收到服務(wù)器的SYN+ACK包,向服務(wù)器發(fā)送確認包ACK(ack=k+1),此包發(fā)送完畢,客戶端和服務(wù)端進入ESTABLISHED(TCP連接成功)狀態(tài),完成三次握手。
    A:你好,B

為什么需要三次握手,而不是兩次?

client發(fā)送了第一個連接的請求報文,但是由于網(wǎng)絡(luò)不好,這個請求沒有立即到達服務(wù)端,而是在某個網(wǎng)絡(luò)節(jié)點中滯留了,直到某個時間才到達server,本來這已經(jīng)是一個失效的報文,但是server端接收到這個請求報文后,還是會想client發(fā)出確認的報文,表示同意連接。假如不采用三次握手,那么只要server發(fā)出確認,新的建立就連接了,但其實這個請求是失效的請求,client是不會理睬server的確認信息,也不會向服務(wù)端發(fā)送確認的請求,但是server認為新的連接已經(jīng)建立起來了,并一直等待client發(fā)來數(shù)據(jù),這樣,server的很多資源就沒白白浪費掉了,采用三次握手就是為了防止這種情況的發(fā)生,server會因為收不到確認的報文,就知道client并沒有建立連接。這就是三次握手的作用。

斷開連接:四次揮手

TCP四次揮手.jpg
  • 第一次揮手
    TCP發(fā)送一個FIN(結(jié)束),用來關(guān)閉客戶到服務(wù)端的連接。
    客戶端進程發(fā)出連接釋放報文,并且停止發(fā)送數(shù)據(jù)。釋放數(shù)據(jù)報文首部,F(xiàn)IN=1,其序列號為seq=u(等于前面已經(jīng)傳送過來的數(shù)據(jù)的最后一個字節(jié)的序號加1),此時,客戶端進入FIN-WAIT-1(終止等待1)狀態(tài)。 TCP規(guī)定,F(xiàn)IN報文段即使不攜帶數(shù)據(jù),也要消耗一個序號。

  • 第二次揮手
    服務(wù)端收到這個FIN,他發(fā)回一個ACK(確認),確認收到序號為收到序號+1,和SYN一樣,一個FIN將占用一個序號。
    服務(wù)器收到連接釋放報文,發(fā)出確認報文,ACK=1,ack=u+1,并且?guī)献约旱男蛄刑杝eq=v,此時,服務(wù)端就進入了CLOSE-WAIT(關(guān)閉等待)狀態(tài)。TCP服務(wù)器通知高層的應(yīng)用進程,客戶端向服務(wù)器的方向就釋放了,這時候處于半關(guān)閉狀態(tài),即客戶端已經(jīng)沒有數(shù)據(jù)要發(fā)送了,但是服務(wù)器若發(fā)送數(shù)據(jù),客戶端依然要接受。這個狀態(tài)還要持續(xù)一段時間,也就是整個CLOSE-WAIT狀態(tài)持續(xù)的時間。
    客戶端收到服務(wù)器的確認請求后,此時,客戶端就進入FIN-WAIT-2(終止等待2)狀態(tài),等待服務(wù)器發(fā)送連接釋放報文(在這之前還需要接受服務(wù)器發(fā)送的最后的數(shù)據(jù))。

  • 第三次揮手
    服務(wù)端發(fā)送一個FIN(結(jié)束)到客戶端,服務(wù)端關(guān)閉客戶端的連接。
    服務(wù)器將最后的數(shù)據(jù)發(fā)送完畢后,就向客戶端發(fā)送連接釋放報文,F(xiàn)IN=1,ack=u+1,由于在半關(guān)閉狀態(tài),服務(wù)器很可能又發(fā)送了一些數(shù)據(jù),假定此時的序列號為seq=w,此時,服務(wù)器就進入了LAST-ACK(最后確認)狀態(tài),等待客戶端的確認。

  • 第四次揮手
    客戶端發(fā)送ACK(確認)報文確認,并將確認的序號+1,這樣關(guān)閉完成。
    客戶端收到服務(wù)器的連接釋放報文后,必須發(fā)出確認,ACK=1,ack=w+1,而自己的序列號是seq=u+1,此時,客戶端就進入了TIME-WAIT(時間等待)狀態(tài)。注意此時TCP連接還沒有釋放,必須經(jīng)過2??MSL(最長報文段壽命)的時間后,當客戶端撤銷相應(yīng)的TCB后,才進入CLOSED狀態(tài)。
    服務(wù)器只要收到了客戶端發(fā)出的確認,立即進入CLOSED狀態(tài)。同樣,撤銷TCB后,就結(jié)束了這次的TCP連接。可以看到,服務(wù)器結(jié)束TCP連接的時間要比客戶端早一些。

A:B,我不想玩了
B:哦,A你不想玩了啊,我知道了
(此時,只是A不想玩了,即不再發(fā)送數(shù)據(jù),但B可能還有未發(fā)送完的數(shù)據(jù),所以需要等待B也主動關(guān)閉)
B:A,好吧,我也不玩了,再見
A:好的,再見

為什么需要四次揮手?

關(guān)閉連接時,當收到對方的FIN報文通知時,它僅僅表示對方?jīng)]有數(shù)據(jù)發(fā)送給你了;但未必你所有的數(shù)據(jù)都全部發(fā)送給對方了,所以你可以未必會馬上會關(guān)閉SOCKET,也即你可能還需要發(fā)送一些數(shù)據(jù)給對方之后,再發(fā)送FIN報文給對方來表示你同意現(xiàn)在可以關(guān)閉連接了,所以它這里的ACK報文和FIN報文多數(shù)情況下都是分開發(fā)送的。
可能有人會有疑問,tcp我握手的時候為何ACK(確認)和SYN(建立連接)是一起發(fā)送。揮手的時候為什么是分開的時候發(fā)送呢?因為當Server端收到Client端的SYN連接請求報文后,可以直接發(fā)送SYN+ACK報文。其中ACK報文是用來應(yīng)答的,SYN報文是用來同步的。但是關(guān)閉連接時,當Server端收到FIN報文時,很可能并不會立即關(guān)閉 SOCKET,所以只能先回復(fù)一個ACK報文,告訴Client端,"你發(fā)的FIN報文我收到了"。只有等到我Server端所有的報文都發(fā)送完了,我才能發(fā)送FIN報文,因此不能一起發(fā)送。故需要四次揮手。

客戶端突然掛掉了怎么辦?

正常連接時,客戶端突然掛掉了,如果沒有措施處理這種情況,那么就會出現(xiàn)客戶端和服務(wù)器端出現(xiàn)長時期的空閑。解決辦法是在服務(wù)器端設(shè)置保活計時器,每當服務(wù)器收到客戶端的消息,就將計時器復(fù)位。超時時間通常設(shè)置為2小時。若服務(wù)器超過2小時沒收到客戶的信息,他就發(fā)送探測報文段。若發(fā)送了10個探測報文段,每一個相隔75秒,還沒有響應(yīng)就認為客戶端出了故障,因而終止該連接。

累計確認

為了保證順序性,每個包都有一個 ID。在建立連接的時候會商定起始 ID 是什么,然后按照 ID 一個個發(fā)送,為了保證不丟包,需要對發(fā)送的包都要進行應(yīng)答,當然,這個應(yīng)答不是一個一個來的,而是會應(yīng)答某個之前的 ID,表示都收到了,這種模式成為累計應(yīng)答或累計確認。

為了記錄所有發(fā)送的包和接收的包,TCP 需要發(fā)送端和接收端分別來緩存這些記錄,發(fā)送端的緩存里是按照包的 ID 一個個排列,根據(jù)處理的情況分成四個部分:1、發(fā)送并且確認的;2、發(fā)送尚未確認的;3、沒有發(fā)送等待發(fā)送的;4、沒有發(fā)送并且暫時不會發(fā)送的。這里的第三部分和第四部分就屬于流量控制的內(nèi)容。

對于接收端來講,它的緩存里面的內(nèi)容要簡單一些:1、接收并且確認過的;2、還沒接收,但是馬上就能接收的;3、還沒接收,但也無法接收的。

TCP為什么是可靠連接

  • 通過TCP連接傳輸?shù)臄?shù)據(jù)無差錯,不丟失,不重復(fù),且按順序到達。
  • TCP報文頭里面的序號能使TCP的數(shù)據(jù)按序到達。
  • 報文頭里的確認序號能保證不丟包,累計確認及超時重傳機制。
  • TCP擁有流量控制及擁塞控制的機制。

二、UDP

包頭

UDP包頭.jpg

特點

  • 不需要大量的數(shù)據(jù)結(jié)構(gòu)、處理邏輯和包頭字段
  • 不會建立連接,但會監(jiān)聽指定端口,誰都可以傳給它數(shù)據(jù),它也可以傳給任何人數(shù)據(jù),可以同時傳給多個人數(shù)據(jù)
  • 不會根據(jù)網(wǎng)絡(luò)的情況進行擁塞控制,無論是否丟包,它該怎么發(fā)還是怎么發(fā)
主要應(yīng)用場景
  • 需要資源少,網(wǎng)絡(luò)情況穩(wěn)定的內(nèi)網(wǎng),或者對丟包不敏感的應(yīng)用。比如DHCP就是基于UDP協(xié)議的
  • 不需要一對一溝通、建立連接,而是可以廣播的應(yīng)用。因為它不面向連接,所以可以做到一對多,承擔(dān)廣播或多播的協(xié)議
  • 需要處理速度快,可以容忍丟包,但是即使網(wǎng)絡(luò)擁塞,也毫不退縮、一往無前的時候
基于UDP的幾個例子
  • 直播。直播對實時性要求比較高,寧可丟包,也不要卡頓,所以很多直播應(yīng)用都基于UDP實現(xiàn)自己的視頻傳輸協(xié)議
  • 實時游戲。游戲的特點也是實時性比較高,在這種情況下,采用自定義的可靠的 UDP 協(xié)議,自定義重傳策略,能夠把產(chǎn)生的延遲降到最低,減少網(wǎng)絡(luò)問題對游戲造成的影響
  • 物聯(lián)網(wǎng)。一方面,物聯(lián)網(wǎng)領(lǐng)域中斷資源少,很可能知識個很小的嵌入式系統(tǒng),而維護 TCP 協(xié)議的代價太大了;另一方面,物聯(lián)網(wǎng)對實時性的要求也特別高。比如 Google 旗下的 Nest 建立 Thread Group,推出了物聯(lián)網(wǎng)通信協(xié)議 Thread,就是基于 UDP 協(xié)議的

TCP和UDP對比

  • TCP是面向連接的,UDP是面向無連接的
    在互通之前,面向連接的協(xié)議會先建立連接,如TCP三次握手,但UDP不會
  • UDP程序結(jié)構(gòu)較簡單
  • TCP是面向字節(jié)流的,UDP是基于數(shù)據(jù)報的
  • TCP保證數(shù)據(jù)正確性,UDP可能會丟包
  • TCP保證數(shù)據(jù)順序,UDP不保證
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容