遠程網絡通訊協議

現代互聯網開發過程中,無論是什麼架構系統,無法避免的並且很重要的一個環節就是網絡通訊,好的網絡通訊方案和協議會讓整個程序效率和耗時變得更低,而JAVA開發過程中我們一般接觸到的都是基於TCP/IP的網絡協議,所以一個優秀的軟件工程師,必備技術棧之一就是對遠程網絡協議有一定的瞭解

OSI七層網絡模型

一般我們說的網絡模型都是OSI網絡模型,而所謂的OSI網絡模型一般分為七層,這七層從上到下分別為(應用層-->表示層-->會話層-->傳輸層-->網絡層-->數據鏈路層-->物理層):

應用層-->表示層-->會話層-->傳輸層-->網絡層-->數據鏈路層-->物理層

大概的訪問調用如圖所示:

遠程網絡通訊協議

有圖可以看出,OSI的網絡模型將每一個步驟分的特別細緻,而在我們開發過程中,最常接觸到的一般是基於OSI的二層協議--TCP/IP協議

TCP/IP四層(五層)網絡模型

看到這個標題一定會有人奇怪,到底是四層還是五層模型啊,其實TCP/IP基於OSI的模型,將其中一部分操作合併為一個模型,而傳統認為是四層模型,分別為:

應用層-->傳輸層-->網絡層-->網絡接口層

即與OSI對應的模型關係如下:

遠程網絡通訊協議

而有些人認為網絡接口層不應該合併數據鏈路層和物理層,這兩層在表現上是不同的,所以就有了五層模型,三種模型之間的比較圖如下:

遠程網絡通訊協議

TCP/IP請求流程

弄懂了TCP/IP大概的模型,我們來思考一個問題,即這四層模型分別是用來幹啥的?又做了什麼處理?在思考這些問題之前,我們先來了解這四層網絡模型分別包括哪些東西

應用層

超文本傳輸協議(HTTP):萬維網的基本協議

文件傳輸(TFTP簡單文件傳輸協議)

遠程登錄(Telnet),提供遠程訪問其它主機功能,它允許用戶登錄

internet主機,並在這臺主機上執行命令.

網絡管理(SNMP簡單網絡管理協議),該協議提供了監控網絡設備的方法,以及配置管理,統計信息收集,性能管理及安全管理等.

域名系統(DNS),該系統用於在internet中將域名及其公共廣播的網絡節點轉換成IP地址

網絡層

Internet協議(IP)

Internet控制信息協議(ICMP)

地址解析協議(ARP)

反向地址解析協議(RARP)

網絡接口層

網絡訪問層又稱作主機到網絡層(host-to-network).網絡訪問層的功能包括IP地址與物理地址硬件的映射,以及將IP封裝成幀.基於不同硬件類型的網絡接口,網絡訪問層定義了和物理介質的連接

接下來,我們看看一個完整請求打來後,TCP/IP的四層模型的大概處理流程是什麼:

遠程網絡通訊協議

從上圖我們可以看到,當客戶端發起請求的時候(應用層),傳輸層會根據你發來的請求,將請求中添加Tcp頭信息,並且傳遞倒網絡層,在網絡層中,會將當前請求處理/計算(獲取出ip地址等信息),添加Ip首部信息到請求中,接著傳遞到了數據鏈路層,在這一層中我們會依照IP地址再去給當前請求計算出一個Mac碼,由於IP還存在重複的情況,而MAC地址是唯一的,這個時候將MAC首部信息加入請求中,根據當前的請求就可以識別出唯一的請求了。

當數據傳輸到服務端的時候,會將傳遞來的request請求進行解析,但是需要注意的是這裡解析的順序與請求的順序相反,首先從數據鏈路層解析掉MAC首部信息,將剩下的請求信息繼續往上傳遞,然後解析Ip首部信息,再去解析Tcp首部信息、端口和請求報文參數等,根據端口等找到對應的進程,進行響應操作,這樣就是一個完整的調度流程

ARP尋址協議

上面我們有介紹到封裝請求的過程中,我們首先將IP首部信息存入請求中,然後再去存入MAC首部信息,這裡不禁會有一個疑惑,IP和MAC有什麼關係嗎?其實我們任何一臺設備都會有一個MAC和一個IP信息進行對應,客戶端發起請求的時候,會利用一個ARP尋址協議的方式找到IP對應的MAC信息,此協議大至如下:當我們已知機器的IP的時候,發起一個基於當前IP的廣播消息,而對應IP的機器收到廣播後會返回響應信息,即當前機器對應的MAC首部信息,這樣就可以根據IP獲取到MAC首部信息

注意:為了防止每一次都會發起ARP尋址,本地機器會有緩存策略,一般來說當我們的IP信息進行變更以後,緩存信息就會失效,這個時候才會重新進行ARP尋址

分層負載

分佈式開發的過程中,經常聽到一個專業名詞即--二層負載/四層負載/七層負載,其實這裡的xxx層負載就是指的是負載均衡方案所在的網絡協議的層級(針對與服務端解析的層級--逆向層級)

二層負載

二層負載協議,一般來說是針對MAC首部信息做的負載均衡,例如當前有一個集群,我們希望外部訪問的時候IP地址是一樣的,但是機器的MAC不一致,保證請求分發到每一臺機器上,這時候可以提供一個虛擬的MAC首部信息,解析請求中的MAC信息的時候,將MAC信息修改為集群中需要被分發的機器的真實MAC首部信息,從而達到負載均衡的效果

三層負載

三層負載指的是針對IP層級的負載,和MAC負載(二層負載)很相似,負載均衡服務器對外提供一個虛擬IP首部信息,當解析請求的時候,修改虛擬IP為真實的被分發的機器的IP,達到負載均衡的效果

四層負載

四層負載針對在OSI模型的傳輸層中,這一層中一般都是TCP/UDP這類的協議,而這一層一般都是封裝了當前客戶端的請求報文信息(包含源IP,目標IP,當前端口號以及目標端口號等),所以四層負載的實現方案一般都是接受到請求信息以後,修改請求數據中的IP/端口號的信息,來分發到不同的應用程序中(此類負載均衡例如:Nginx)

七層負載

除了上面常見的幾種負載均衡以外,還有一種特殊的負載,叫七層負載,這種負載一般是在應用層做的操作,而應用層一般都是客戶端請求交互層,這一層中一般只有HTTP/DNS等協議,所以在當前層,我們可以做到的負載條件很多,比如根據不同的URL,不同的請求類型等都可以實現分發到不同的服務器上

TCP/IP的握手協議與揮手協議

三次握手

tcp的連接是通過三次握手協議完成有效連接建立的,所謂的三次握手就是客戶端和服務端在連接過程中,總共發送三個包來相互之間確認並建立聯繫,而在sokect編程中,握手的過程由connect來觸發

遠程網絡通訊協議

上圖我們可以看出來三次握手的過程為:

第一次握手:客戶端發送了一個SYN為1標誌包,指明客戶端將要連接的服務器端口,並且初始化序號X保存在序列號(Sequence Number)字段中,發送完畢以後,客戶端的狀態變更為SYN-SENT

第二次握手:服務器收到了客戶端的請求,發送回確認包標誌ACK以及客戶端發送來的SYN應答為1,並且服務端選擇ISN序列號Y,存放到Seq中,將確認的序列號(

Acknowledgement Number)設置為客戶端發來sql+1,當發送完畢後,服務端狀態變更為SYN-RCVD

第三次握手:客戶端再次確認ACK,Ack為1,並且把服務端的ACK+1放在序列seq中,將服務端的序列+1放入確認字段ack中,在發送完畢以後,客戶端俄日ESTAB-LISHED狀態,當服務端也收到這個確認包以後,也會進入ESTAB-LISHED狀態,此時握手結束

四次揮手

與連接的時候三次握手不同,斷開連接的時候需要四次揮手的過程才能保證一定是關閉連接:

遠程網絡通訊協議

第一次揮手:客戶端需要斷開連接的時候,發送一個FIN為1的包,表示我已經沒有數據需要發送了,可以準備斷開連接,但是這個時候我還可以接受你的數據,當發送完畢後,狀態為FIN-WAIT-1

第二次揮手:服務端拿到了客戶端發來的FIN標誌位,發送一個確認包,表示當前已經收到了你的關閉連接的請求,ACK為1,生成seq序列,並且將客戶端發來的seq+1作為ack確認字段進行應答,發送完畢後服務端狀態為CLOSE-WIAT狀態,當客戶端受到應答以後,狀態變更為FIN-WAIT-2,但是這個時候服務端還沒關閉,可能還存在需要發送的數據

第三次揮手:當服務端沒有數據需要發送的時候,會再次發送一個包,FIN為1,ACK為1,生成序列seq,並且將上一次的ack確認字段繼續發送過來,發送完畢後,服務端處於LAST-ACK狀態

第四次揮手:客戶端收到了來自服務端的將要關閉的包,併發出一個確認包,將服務端的ack作為seq,並且將服務端的seq+1作為ack確認字段再次發送過去,這個時候客戶端會進入

TIME-WAIT狀態,並等待2MSL時間,這個時候服務端收到了響應,就會關閉連接,或者等待了2MSL以後,客戶端沒有收到響應,也會認為服務端已經關閉,也會進行關閉操作

SYN攻擊

在三次握手的過程中,服務端發送了ack確認字段給客戶端後,收到ack的客戶端連接稱之為半連接,如果這個時候客戶端不返回確認包,那麼服務端會重發直到超時,但是如果段時間內偽造大量的不存在的客戶端ip發起連接請求,服務端等待客戶端確認一直等待不到,所以短時間內大量無用的連接佔用隊列,導致正常的用戶連接阻塞導致網絡癱瘓,SYN攻擊是最常見的DDOS攻擊,所以有效的檢測SYN攻擊和防護很重要,防護方案常見如下:

1.過濾網關防護 2.加固TCP/IP協議線

為什麼TCP/IP是三次握手,不是二次也不是四次?

三次握手是因為因為當 Server 端收到 Client 端的 SYN 連接請求報文後,可以直接發送

SYN+ACK 報文。其中 ACK 報文是用來應答的,SYN 報文是用來同步的。但是關閉連接時,

當 Server 端收到 FIN 報文時,很可能並不會立即關閉 SOCKET(因為可能還有消息沒處理

完),所以只能先回復一個 ACK 報文,告訴 Client 端,"你發的 FIN 報文我收到了"。只有等到

我 Server 端所有的報文都發送完了,我才能發送 FIN 報文,因此不能一起發送。故需要四步

握手

為什麼四次揮手以後還要等待2MSL才正式關閉?

網絡是不可靠的,雖然收到服務端的確認以後,客戶端發出確認以後已經可以close,但是,可能出現失敗需要重試或者網絡卡頓導致,客戶端發出時間接近一次MSL時間,服務端返回也接近MSL時間,可能性都有,所以為了保險起見,等待到兩個最大的時間後還收不到返回的消息,才可以認為是服務端關閉了

TCP的IO通信原理

雙工協議

TCP 是一個全雙工協議,數據通信允許數據同時在兩個方向上傳輸,因此全雙工是兩個單工

通信方式的結合,它要求發送設備和接收設備都有獨立的接收和發送能力,常見的協議如下:

協議概念單工協議數據傳輸只支持數據在一個方向傳輸半雙工協議數據傳輸允許數據在兩個方向傳輸,但是在某個時刻,只能在一個方向傳輸全雙工協議允許數據同時在兩個方向上傳輸,要求設備有獨立的接收和發送的能力

IO通信過程

TCP、UDP 都是在基於Socket 概念上為某類應用場景而擴展出的傳輸協議,而socket 是一種

抽象層,應用程序通過它來發送和接收數據,就像應用程序打開一個文件句柄,把數據讀寫

到磁盤上一樣。使用 socket 可以把應用程序添加到網絡中,並與處於同一個網絡中的其他應

用程序進行通信。不同類型的 Socket 與不同類型的底層協議簇有關聯。主要的 socket 類型

為流套接字(stream socket)和數據報文套接字(datagram socket)。 stream socket 把 TCP作為端對端協議(底層使用 IP 協議),提供一個可信賴的字節流服務。數據報文套接字

(datagram socket)使用 UDP 協議(底層同樣使用 IP 協議)提供了一種“盡力而為”的數據

報文服務,瞭解了Socket以後,我們來了解下tcp的io通信過程:

對於 TCP 通信來說,每個 TCP Socket 的內核中都有一個發送緩衝區和一個接收緩衝

區,TCP 的全雙工的工作模式及 TCP 的滑動窗口就是依賴於這兩個獨立的 Buffer 和該 Buffer

的填充狀態。而接收緩衝區把數據緩存到內核,若應用程序一直不調用Socket的read方法讀取,那麼則該數據一直存在緩衝區中,而read方法就是把數據複製到應用層的buffer中。而調用send方法的時候一般是把數據從應用層的buffer中,讀取到Socket內核緩衝區,將數據返回,但是如果應用一直不讀取,那麼buffer滿了以後,如果對端的窗口關閉,tcp緩存區的數據不會移除,這也證實了TC是可靠傳輸的。如果傳輸的數據超過了窗口的大小,那麼接收方會把剩下的數據丟棄

遠程網絡通訊協議

遠程網絡通訊協議

滑動窗口

早期的網絡通信過程中,由於不會考慮到網絡擁擠的情況導致數據丟失而直接發送數據,所以後來為了解決這個問題,就出了一個流量控制技術--滑動窗口協議,發送方和接收方都要維護一個數據幀的序列,這個序列稱之為窗口

窗口尺寸:可以不等待應答而繼續發送數據的最大的幀稱之為窗口尺寸

發送窗口:可以不等待應答繼續發送的窗口

接受窗口:接受發送來的數據,落在當前窗口中的幀,一定會被處理,但是落在窗口外的數據,允許被丟棄的窗口

這點可以參照在線的滑動窗口演示:

https://media.pearsoncmg.com/aw/ecs_kurose_compnetwork_7/cw/content/interactiveanimations/selective-repeat-protocol/index.html

為感謝各位的長期關注,準備了十二本Java、Android書籍回饋給粉絲用戶,憑手氣獲得,可以私聊我瞭解詳情喔~

既然來了,點個關注再走唄~


分享到:


相關文章: