網絡協議圖
一.UDP?
特點:
無連接,不可靠,面向數據報,全雙工(前面網絡編程中介紹過)
?格式:
?
?服務器的端口號一般都是程序員指定的(這樣你才能訪問到),客戶端的端口號是系統自動分配的(如果提前指定好, 可能會與其他程序沖突)
UDP的長度問題
也許你也會有一個問題:在當今的世界, UDP的報文最大長度為64kb,是否夠用?
顯然是不夠用的,這也是UDP的最大痛點,也是被邊緣化的主要原因
為什么設計UDP的大佬不做出改變,將UDP報頭的表示長度的屬性不設計更大一點4字節?6字節?
不是技術問題,是zz問題↓
要傳輸一個超過64kb的數據該怎么辦?
有兩個方案
?校驗和
?
?上述的比特翻轉本來就是小概率事件, 敲好兩個反轉能抵消的概率小之又小, 工程上可以忽略
UDP發現數據校驗不對時,只能丟棄不會重發, 也是不可靠傳輸的體現,想要重發要么使用TCP,要么在應用層代碼中自己實現
二.TCP
特點:
有連接, 可靠傳輸,面向字節流,全雙工
格式
?像上面的32位序號和確認序號16位窗口大小和緊急指針,還有那六個標志位后面會介紹到
三.TCP的十大核心機制
核心機制一:確認應答(可靠性機制)
TCP的可靠傳輸是內核實現的,寫代碼的時候是感知不到的
可靠傳輸的實現機制是 確認應答(我給對方發消息,對方收到之后給我一個應答說確認收到了),確認應答是保證可靠傳輸的最核心的機制
再說一下確認應答的后發先至
比如我給女神發消息
本來是
結果是可能是
當連續發多條數據的時候,可能就會出現后發先至的情況(一個數據報是先發的,反而后到了)
怎么產生的呢?
?如何解決?
針對數據編號,就要用到報頭中的32位序號了
?
?
應答報文可能攜帶載荷也可能不攜帶
引入序號之后接收方就可以根據序號順序排序來依次讀取數據了
核心機制二:超時重傳(可靠性機制)
在傳輸數據的過程中,還可能發生“丟包”,也就是發送一個數據在傳輸的過程中丟了,沒有到達對方
在兩個主機之間,網絡的結構是非常復雜的,中間要經過很多路由器和交換機,這些路由器和交換機同時也連接著其他的路由器和交換機,這些結果錯綜復雜,傳輸的數據量也是不確定,有時候傳輸的數據可能會多點,有時候可能會少點
如果設備太繁忙,這些數據包就需要等待,如果等太久了,就可能被丟棄了,網絡負載越高,線路就越繁忙,就越容易丟包某段路線出現強烈信號干擾也會丟包
真的出現丟包怎么辦呢??
重傳!設置一個時間,在規定的時間里面沒有收到回應,就重新傳輸這個數據,這個就叫做超時重傳
?兩種丟包的情況
以下兩種情況接收無法分辨, 都會觸發重傳
第一種情況(要傳輸的數據包丟了)
?這種情況發送的數據丟了再重新傳一次就好了 主要還是第二種情況
第二種情況(返回的ACK應答數據包丟了)
接收緩沖區在操作系統內核中會分配一個專門緩沖區存儲數據等待TCP協議棧處理,類似于生產者消費者模型
確認應答是tcp保證可靠性的最核心機制;超時重傳是TCP可靠性機制的有效補充,這兩個機制保證了tcp的可靠性傳輸,并不是三次握手
核心機制三:連接管理 [網絡這個模塊最常考的部分]
1.建立連接(三次握手)
tcp是有連接的 客戶端與服務器是通過三次握手來建立連接的
?這個時候就有疑問了:明明三次握手上面確實是四次握手?
這里的中間兩次握手可以合并為一次↓
?
為什么能合并?
其實syn和ack打包是在操作系統內核中完成的 時間上可以說是同步的,tcp也允許在報頭中設置多個標志位(ACK和SYN都為1) 同時合并也能減少開銷提升效率
三次握手傳輸的是什么?
傳輸的數據的序號從幾開始,往往兩次連接的初始序號差別很大(這里就為了防止前朝的劍斬本朝的官問題后面會介紹到) 還會告訴對端的IP和端口號并且互相保存(有連接的體現)這是網絡層IP協議要做的(每次網絡傳輸都會涉及最開頭那張圖的封裝分用)
三次握手TCP層的狀態
上述只是簡單描述了一下三次握手,實際的三次握手比這個更加復雜,如下圖框出的地方(再下面是傳輸數據和四次揮手的過程)
?各狀態的介紹
上述狀態常見的就是listen和establish
?為啥tcp要三次握手,有啥用,解決了啥問題?
1.投石問路,先初步探一探網絡通信鏈路是否通暢(網絡通常是可靠傳輸的前提條件)
2.驗證通信雙方的發送能力和接收能力是否正常
討論:兩次握手是否可行?
不行,兩次握手少了一步給服務器發ack,這會讓服務器不知道服務端的接收能力是否正常和服務器的發送功能是否正常
四次握手是否可行?
可以,但是沒必要,浪費資源,效率較低
3.可以協商一些關鍵信息
也如前面所說防止出現前朝劍斬本朝官?
2.斷開連接(四次揮手)?
過程
問題:四次揮手的中間兩次能否合并變成三次揮手?
有時候能有時候不能
不能:ack和fin的交互時機不一樣ack是在操作系統內核中就完成了,fin需要應用層應應用程序調用close方法,時機不同所以就不能合并,而三次握手之所以能是因為ack和syn都是在內核中完成的交互時機可以說瞬發,就可以合并
能:tcp有延遲應答機制,可以延遲發送ack,這樣就可以和fin同步了
雖然有時候能有時候不能,但是大多數情況下還是不能
四次揮手TCP層的狀態
如圖圈出來的
?重點就關注close_wait和time_wait狀態
close_wait狀態介紹?
?time_wait狀態介紹
time_wait要等多久才合適呢?
2*MSL(網絡上任何兩個節點傳輸所要消耗的最大時間)?通常會配置成60s ,2*MSL也就是兩分鐘
MSL每個系統配置的都不一樣,也能修改
異常情況

再談TCP式如何實現可靠傳輸的?
確認應答
超時重傳
連接管理(三次握手,四次揮手)(握手揮手的過程也是依靠確認應答和超時重傳實現可靠傳輸的)
這些機制都起到了作用,在三次握手中,一旦路探完了,后續就沒它事了,網絡環境事多變的,可能這會暢通,過會就堵塞了,而確認應答,是保證每次傳輸的這些數據都是可靠的,因此真正起到決定性作用的還是確認應答!
核心機制四:滑動窗口(提高提高傳輸效率)
更準確地說,是讓TCP在可靠傳輸的前提下,效率別太拉跨,因為可靠傳輸效率已經降低了(可靠和效率不可兼得)
使用滑動窗口,不能讓TCP變得比UDP快,但是可以縮小差距
下一組是怎么發的?
1.等待所有ack都收到再發下一組
2.收到一個發一個
很明顯是第二種,第一種并不能節省多少時間,甚至會等待更長時間?
如果2001比1001的ack先收到會怎么樣?
如果這樣的情況窗口直接往后走兩個就行了, ack確認序號的含義是該序號之前的數據都已經收到了,比如數據1-50收到了 71-100收到了51-70沒收到,返回的ack確認序號也是51不會是101,等到后續收到51-70才會發送確認序號為101的應答報文
丟包問題
?情況一:數據包已經抵達,ack卻丟了
這種情況不要緊,因為可以通過后續的ACK進?確認;?也就是上面所說的確認序號的作用
情況二:數據包直接就丟了
重傳采用的是快速重傳機制(滑動窗口下的,超時重傳的變種操作)
快速重傳就是只要誰丟了就重傳誰,其他的數據(都已經在接收緩沖區里呆著)不用重傳,整個過程速度很快
接收方的緩沖區情況↓
超時重傳和快速重傳并不沖突而是相輔相成
核心機制五:流量控制(作為滑動窗口補充)
滑動窗口的窗口越大,傳輸效率越高
但是窗口也不能無限大,如果窗口太大了,就可能使接收方處理不過來了(和你代碼有關系),或者是使傳輸的中間鏈路處理不過來,這樣就會出現丟包,就得重傳了,這時候窗口大并沒有提高效率,反而降低效率了
流量控制就是給滑動窗口睬踩剎車,避免窗口太大,導致接收方處理不過來?
?*滑動窗口的窗口大小是實時變化的
?具體流程
?光考慮接收方,還是不夠的,還需要考慮中間鏈路的處理能力(也就是擁塞控制)
核心機制六:擁塞控制
總的傳輸速率是一個木桶效應,取決于最短板
具體怎樣衡量中間設備的轉發能力呢?
此處并不會對中間設備的轉發能力進行量化,因為中間設備那么多也不好逐個進行量化,更何況網絡環境還是動態變化的,而是把中間的設備都看成一個整體,采取“做實驗”的方式,動態調整,產出一個合適的窗口大小
這樣做也可以非常好的適應網絡環境的動態變化?
方案↓
?
實際發送方的窗口 取決于擁塞窗口,流量控制窗口的最小值
擁塞控制喝流量控制共同限制了滑動窗口機制,可以讓滑動窗口能夠在保證可靠性的前提下,提高傳輸效率了
也就是說擁塞控制和流量控制也是保證可靠性的機制?
核心機制七:延遲應答(提高傳輸效率的機制).
(延遲應答也是圍繞滑動窗口來展開的)
是否有辦法在條件允許的基礎上,盡可能地提高窗口大小呢?
需要在返回ack的時候,拖延一點時間,利用拖延的這個時間,就可以給應用程序騰出來更多的消費數據的時間,這樣接受緩沖區的剩余空間就更大了!
?
此處通過延時應答到底能提高多少速率,還是取決于接收方應用程序實際的處理能力(也不是百分百提升效率還是看應用程序消費的快不快,也有可能延時的時候又收到了其他數據)
?核心機制八:捎帶應答
在延遲應答的基礎上,引入的第一個進一步提高效率的方式
延遲應答使讓ack傳輸的時機更慢
捎帶應答使基于延遲應答,讓數據進行合并
核心機制九:面向字節流(粘包問題)?
這里主要討論粘包問題至于這個粘讀zhan和nian的都有
有以下情況?
解決辦法
?已經有成熟的方案例如json和protobuf已經解決粘包問題,但是自定義應用層協議的時候就要考慮到這個問題
核心機制十:TCP異常情況的處理(經典面試題)
?網絡本身就會存在一些變數,導致tcp連接不能繼續正常工作了
比如
1.進程崩潰
進程崩潰=>進程沒了=>PCB沒了=>文件描述符表也就被釋放了=>相當于調用socket.close()(socket在系統內核中也是一個文件,也會被放到文件描述符表中)=>崩潰的這一方就會發出FIN,進一步的觸發四次揮手,此時連接就正常釋放了,此時tcp的處理和進程的正常退出沒啥區別
?2.主動關機
?3.主機掉電了
心跳包
?4.網線斷開了
?
以上就是TCP的十個主要特性,并不是只有這十個特性,還有很多特性在標準文檔中??
?補充:tcp報頭其他屬性
TCP和UDP對比
如何實現UDP的可靠傳輸,就往TCP上面靠
?
?