一.TCP/IP協議族的四層模型
應用層(HTTP FTP),傳輸層(TCP UDP),網路層(IP),鏈路層。
二.為什麼要分層?
因為網路傳輸的過程中網路是不穩定的。
如圖:
其實在我們的網路傳輸過程中從客戶端傳送訊息的服務端的過程中網路並不是只沿著一條直線可以直接順利傳達到的,它再傳輸的過程中會經過很多的中間節點,但每一個節點都是有可能是會突然出問題的。如圖所示:舉一個極端的例子我在傳資料的過程中突然停電了或者某一個節點的路由壞了,這時我們的資料就相當於傳輸失敗了,那麼這時候我們就需要重新傳輸資料。但是如果傳輸的是一個非常大的資料呢?那麼我們每次重新傳輸這個資料的時候必然會造成流量的浪費和速率的降低。如圖:每次傳輸失敗我都需要將資料 ABCDEFGH 從新傳送,效率很低!!!
這也就是為什麼需要傳輸層的原因。
三.傳輸層:TCP協議, UDP協議
傳輸層主要做的是將你應用層的資料分塊編號傳輸,同時還要確認你的資料到達,如果某一塊的資料沒有到達那麼我只需要再次傳輸傳輸失敗的內容即可。這樣就保證了我只需要傳輸失敗的部分而不是每次都整體重新傳輸。
如圖:我們將原資料拆分為四組資料
當我們傳輸資料的過程中每次將資料傳到服務端的TCP層時,它都會確認並通知客戶端對應的編號資料已到達。這時比如3號的傳輸過程中傳輸失敗了那麼客戶端是遲遲不能收到服務端回應的,對此我們要做的只是再重新傳輸失敗的3號即可而不是像之前一樣整體重新傳輸。
1.TCP協議
所做的事情:保證可靠性和拆塊資料
- 客戶端TCP層將HTTP層資料拆塊。
- 傳輸資料完成後服務端需要向客戶端傳送收到資訊,如果在規定時間內客戶端沒有收到服務端傳送的回應(ACK)則客戶端將重新傳送沒有收到的資料。(超時重傳,保證可靠性)。
- 所有資料傳輸完成後服務端TCP層將拆塊的資料組合成原有資料交給HTTP層處理。
2.TCP UDP的區別
什麼叫做連線?
通訊雙方建立確認「可以通訊」,不會將對方的訊息丟棄,即為「建立連線」
UDP是面向無連線的、不可靠的資料包服務、有序;
只需找到目標埠號就可以直接開始傳送資料,即傳送資料之前不需要建立連線而TCP要經過3次握手建立連線。UDP不需要確認資料是否丟失是否到達,只管傳就可以。
使用場景: 遊戲、視訊會議等不需要確認資料有效性且需要快速傳輸的場景。比如遊戲吃雞,我卡頓兩秒後恢復了,我不需要知道這卡頓的兩秒發生了什麼不需要知道它的資料是什麼,我只關心2秒後恢復網路的這最新一幀的畫面是什麼。
TCP是面向連線的、可靠、有序的位元組流服務。
3.TCP 協議被認為是穩定的協議
TCP 協議被認為是穩定的協議,因為它有以下特點:(都是為了確保資料不丟失,所有資料都傳輸成功)
- 面向連線,“三次握手”
- 雙向通訊( 客戶端傳送,服務端接收同時告知客戶端接收完成)
- 保證資料按序傳送,按序到達
- 超時重傳
4.滑動視窗協議
為了不浪費網路資源高效的傳送資料,保證可靠性和有序性
- 滑動視窗協議,是TCP使用的一種流量控制方法。該協議允許傳送方在停止並等待確認前可以連續傳送多個分組。由於傳送方不必每發一個分組就停下來等待確認,因此該協議可以加速資料的傳輸。
- 只有在接收視窗向前滑動時(與此同時也傳送了確認),傳送視窗才有可能向前滑動。
- 收發兩端的視窗按照以上規律不斷地向前滑動,因此這種協議又稱為滑動視窗協議。
- 當傳送視窗和接收視窗的大小都等於1時,就是停止等待協議。
上圖中分成了四個部分,分別是:(其中那個黑模型就是滑動視窗)已收到ack確認的資料。
- 已收到ack確認的資料。
- 發還沒收到ack的。
- 在視窗中還沒有發出的(接收方還有空間)。
- 視窗以外的資料(接收方沒空間)
下面是個滑動後的示意圖(收到36的ack,併發出了46-51的位元組):
要注意的是TCP並不是每一個報文段都會回覆ACK的,可能會對兩個報文段傳送一個ACK,也可能會對多個報文段傳送1個ACK【累計ACK】,比如說傳送方有1/2/3 3個報文段,先傳送了2,3 兩個報文段,但是接收方期望收到1報文段,這個時候2,3報文段就只能放在快取中等待報文1的空洞被填上,如果報文1,一直不來,報文2/3也將被丟棄,如果報文1來了,那麼會傳送一個ACK對這3個報文進行一次確認。
4.1 擁塞機制
對傳送端視窗的傳送資料量做控制,可以認為是對傳送視窗的大小不斷地調整防止流量的浪費。(如當前網路情況不好,服務端只能處理50個資料但客戶端傳了100個資料,這時剩下的50個資料相當於沒有處理,那麼客戶端會觸發超時重傳機制重新傳輸這50個資料,這樣的話就造成了一個資源的浪費情況的發生,因為這50個資源是完全沒有必要去傳輸的)。慢啟動,擁塞控制 快重傳,快恢復
5.TCP的三次握手、四次揮手過程 (連線、斷開)
這裡我們要先認識幾個標誌位
ACK:收到。
SYN:發起一個連線。
FIN:釋放一個連線。
5.1 三次握手
簡化三步握手的流程就是
- C發給S我要跟你通訊。
- S告訴C你可以跟我通訊同時我也要跟你通訊。
- C告訴S你可以跟我通訊,我們們可以開始通訊了。
`需要三次握手的原因在於S端在第二次握手(發出訊息)後並不知道C端是否能接收它傳送的訊息,如果傳送的SYN對方沒有收到而直接通訊的話會造成只能C到S單方通訊(C會收不到S傳送的確認訊息收到的資訊),而TCP連線是需要雙端都可以通訊的。`
5.2 四次揮手
- 第一次揮手:客戶端傳送一個FIN=1,用來關閉客戶端到伺服器端的資料傳送,客戶端進入FIN_WAIT_1狀態。意思是說”我客戶端沒有資料要發給你了”,但是如果你伺服器端還有資料沒有傳送完成,則不必急著關閉連線,可以繼續傳送資料。
-
第二次揮手:伺服器端收到FIN後,先傳送ack=u+1,
告訴客戶端,你的請求我收到了,但是我還沒準備好,請繼續你等我的訊息(服務端會等待沒有傳送的資料傳送完畢)
。這個時候客戶端就進入FIN_WAIT_2 狀態,繼續等待伺服器端的FIN報文。 - 第三次揮手:當伺服器端確定資料已傳送完成,則向客戶端傳送FIN=1報文,告訴客戶端,好了,我這邊資料發完了,準備好關閉連線了。伺服器端進入LAST_ACK狀態。
- 第四次揮手:客戶端收到FIN=1報文後,就知道可以關閉連線了,但是他還是不相信網路,怕伺服器端不知道要關閉,所以傳送ack=w+1後進入TIME_WAIT狀態,如果Server端沒有收到ACK則可以重傳。伺服器端收到ACK後,就知道可以斷開連線了。客戶端等待了2MSL(2倍最大報文存活時間)後依然沒有收到回覆,則證明伺服器端已正常關閉,那好,我客戶端也可以關閉連線了。最終完成了四次握手。
注意:是第四次握手2端才分別關閉的!而不是第三次! S端收到ACK後會關閉連線,同時C端傳送ACK後在等待2MSL(2倍最大報文存活時間)後C端連線也會關閉。如果第三次揮手S端直接關閉的話那麼如果C端因為網路因素沒有收到FIN的話那麼C端會一直等待FIN,這時S端已經關閉了將導致C端無法關閉的情況發生。
等待2MSL的原因是S端可能不會收到C端的ACK標誌位,那麼S端會超時重傳重新傳送FIN給C端,如果C端不等待2MSL而直接關閉的話會造成C端收不到FIN而S端一直重傳FIN導致S端無法關閉的情況發生。(一切都是為了保證四次揮手更加可靠)。
5.3 長連線
- 為什麼要長連線?
因為行動網路並不在 Internet 中,而是在運營商的內網,並不具有真正的公網 IP,因此當某個 TCP 連線在一段時間不通訊之後,閘道器會出於網路效能考慮而關閉這條 TCP 連線和公網的連線通道,導致這個TCP端不再能收到外部通訊訊息,即 TCP 連線被動關閉(比如推送接收不到了,聊天場景中的S端給C端發資訊由於連線關閉導致的C端接收不到了)。
- 長連線的實現方式
心跳。即在一定間隔時間內,使用 TCP 連線傳送超短無意義訊息來讓閘道器不能將自己定義為「空閒連線」,從而防止閘道器將自己的連線關閉(防止TCP連線通道被被動的關閉)。
TCP的keep alive是檢查當前TCP連線是否活著;HTTP的Keep-alive是要讓一個TCP連線活久點。它們是不同層次的概念。
四.網路層 IP
網路層的作用是在複雜的網路環境中為要傳送的資料包找到一個合適的路徑進行傳輸。(也就是從眾多的路由節點中選出一條效率最高的路徑去傳輸)
網路層不能保證資料包的可靠性傳輸,可靠性是由網路主機中的傳輸層(TCP)來進行保證的。也就是說網路層不管傳的資料是什麼,也不管你傳沒傳送到達,只管一味的傳輸。(悶頭楞傳~)
如圖:
- 圖a就是有連線(TCP,有序)的傳輸:由主機A向主機B傳輸資料時,提前建立一條連線:主機A->節點1->節點3->主機B。則在由A向B傳輸多個資料包時,均只能使用這條路線進行傳輸。
- 圖b是無連線(UDP,無序)的傳輸:當由A向B傳送資料包1時,從主機A開始發現由A到節點1的網路比較空閒,就使用這條路徑傳送,到達節點1時,發現可以使用節點1到節點3的路徑,於是就走這條路徑,同理再走到主機B;當傳送資料包2時,此時發現由A到節點2的網路比較空閒,就使用這條路線傳送,之後同理。
五.鏈路層
網路層傳輸資料需要建立在物理裝置的基礎上, 鏈路層就是我們平時接觸的網路卡和網路卡的驅動程式(乙太網,WIFI)
。
上層(比如網路層,傳輸層等等)不知道也不需要知道資料在物理上是如何傳輸的。比如資料究竟是用雙絞線傳輸的還是用同軸電纜,到底是有線的網路介面還是無線的網路介面傳輸,這些細節統統不需要鏈路層的上層去操心,這樣的好處就是比如一會使用有線,一會使用無線,這對於處於網路層的IP實現,或者是傳輸層的TCP實現來講,是不需要有任何變化的。