Socket 核心原理分享

ITDragon龍發表於2020-09-21

Socket 的個人故事。希望通過這篇文章讓你弄懂什麼是 Socket,明白 TCP 和 UDP 協議的通訊,明白長連線和短連線的優缺點,明白 BIO、NIO、AIO的區別。

Socket

大家好,我是 Socket。很多人都知道我,但是都不清楚我。給你看一下我和大佬的合影。

我很榮幸能與 TCP/IP 五層模型中的各位大佬站在一起,但我並不屬於他們中的任何一層。我的存在只是為了讓應用層的使用者能更簡單地將資料丟給傳輸層。他們不需要關係 TCP/IP 協議族的複雜內容。有什麼問題直接找我,我來幫你搞定。簡單來說,你們可以把我理解成是應用層與TCP/IP協議族通訊的抽象層、函式庫。

物理層:規範傳輸介質的規格特性(介面大小、形狀、引線數量、電壓範圍等),讓位元流能在各種傳輸媒體之間傳輸。
鏈路層:提供介質訪問和鏈路管理,主要將源計算機網路層來的資料可靠的傳輸到相鄰節點的目標計算機的網路層。
網路層:提供了主機到主機的通訊服務和各種形式的程式到程式的通訊。實現兩個端系統之間的資料透明傳送,使傳輸層不需要了解網路中的資料傳輸和交換技術。
傳輸層:主要負責向兩個主機中程式之間的通訊提供服務。
應用層:為應用程式提供服務。

TCP 和 UDP

前面介紹過,我是應用層和傳輸層之間的抽象層。他們之間的通訊都是通過我來完成,可以把我理解成網路通訊的基本操作單元。有時候通訊多了,可真把我給類壞了。比如很多時候應用層會有多個程式往傳輸層進行通訊。這時候會有多個 TCP (UDP)連線,或者多個應用程式用同一個 TCP (UDP)連線。為了避免各個連線通訊混亂的問題,我可費了不少心思。

我有三寶:協議、IP地址、埠。每個 Socket 都會帶上這三寶,已確保自己能到達正確的目標主機上。
協議:一種約定和規範。只有通訊雙方使用同一種協議才能互相通訊。
地址:目標主機的地址。不管是客戶端還是服務端,都需要一個IP地址。
埠:用於區分網路程式的唯一標識。目標主機上會有很多的網路應用,他們各佔一個埠,互不衝突。

TCP

TCP 傳輸控制協議(Transmission Control Protocol)是一種面向連線、可靠、基於位元組流的傳輸層通訊協議。在建立連線時需要進行三次握手,已確保在不穩定的網路環境下能進行可靠的傳輸。在斷開連線時需要進行四次揮手,已確保雙方通訊的資料完整。

三次握手
第一次握手:從客服端發往服務端,發 syn 包,看能否連上伺服器。需要等待伺服器確認。
第二次握手:從服務端發往客戶端,發 ack 包,通知客戶端你能連上我。同時傳送 syn 包,看能否連上客戶端。需要等待客戶端確認。
第三次握手:從客服端發往服務端,發 ack 包,通知服務端你能連上我。

四次揮手
第一次揮手:從客戶端發往服務端,發 fin 包,告知服務端要斷開連線。
第二次揮手:從服務端發往客戶端,發 ack 包,通知客戶端你的請求我收到了,但是我還沒有準備好,等通知。
第三次揮手:從服務端發往客戶端,發 fin 包,告知客戶端我已經要斷開連線了。
第四次握手:從客戶端發往服務端,發 ack 包,通知服務端你的請求我收到了,如果你不回我訊息,我也斷開連線了。

TCP Socket 通訊流程圖如下。

首先,服務端和客戶端都需要呼叫 socket 函式。用來生成一個用於通訊的套接字檔案描述符 sockfd。
隨後,服務端需要呼叫 bind 函式。開始將伺服器 IP 和 PORT 繫結到第一步建立的 sockfd 上。
然後,伺服器便可以呼叫 listen 函式。此時的套接字狀態從 CLOSE 轉變為 LISTEN,成為一個對外提供 TCP 連線的視窗。監聽著客戶端的連線請求。
一旦,服務端監聽到客戶端的連線請求後,服務端便開始呼叫 accept 函式。接收請求了一些包括客戶端傳來的 IP 和 PORT。若接收成功,還會再建立一個新的 sockfd 與客戶端進行 IO 操作。
最後,在通訊結束後呼叫 close 函式。與客戶端進行四次揮手後關閉,釋放資源。
連線,客戶端發起連線時需要呼叫 connect 函式。將帶上自身的 IP、隨機的 PORT 和 sockfd 向目標伺服器開始三次握手建立連線。

UDP

UDP 使用者資料包協議(User Datagram Protocol)是無連線的,面向訊息的,提供高效率服務。UDP 不需要連線,少了三次握手和四次揮手的操作,從而對資源的佔用率更少、處理的網路請求和響應效率更快。但他不能保障在極端的情況下載通訊不會丟失。

UDP 在繫結目標主機地址後,便可以通過 Sendto 和 Recvfrom 傳送和接受資料。

長連線和短連線

長連線:通訊雙方在有資料互動時建立一個 TCP 連線,並一直保持連線狀態。
短連線:通訊雙方在有資料互動時就建立一個 TCP 連線,資料互動完成後斷開連線。

長連線不需要頻發建立連線,適用於頻繁請求的客戶。減少了短連線頻繁建立連線帶來的資源開銷。但是長連線如果過多也會多伺服器帶來很大的壓力。長連線的應用場景相比短連線要少點。使用建議定時傳送心跳包,以維持連線的狀態。且長連線的數量不宜過多。

短連線對於伺服器而言比較簡單,每個連線都是有用的,不需要像長連線一樣需要額外維護。

BIO NIO AIO

BIO 全稱Block-IO 是一種阻塞同步的通訊模式。我們常說的Stock IO 一般指的是BIO。是一個比較傳統的通訊方式,模式簡單,使用方便。但併發處理能力低,通訊耗時,依賴網速。
NIO 全稱New IO,也叫Non-Block IO 是一種非阻塞同步的通訊模式。
AIO 也叫NIO2.0 是一種非阻塞非同步的通訊模式。在NIO的基礎上引入了新的非同步通道的概念,並提供了非同步檔案通道和非同步套接字通道的實現。

BIO 設計原理:
伺服器通過一個Acceptor執行緒負責監聽客戶端請求和為每個客戶端建立一個新的執行緒進行鏈路處理。典型的一請求一應答模式。若客戶端數量增多,頻繁地建立和銷燬執行緒會給伺服器開啟很大的壓力。後改良為用執行緒池的方式代替新增執行緒,被稱為偽非同步IO。
伺服器提供IP地址和監聽的埠,客戶端通過TCP的三次握手與伺服器連線,連線成功後,雙放才能通過套接字(Stock)通訊。

NIO 設計原理:
NIO 相對於BIO來說一大進步。客戶端和伺服器之間通過Channel通訊。NIO可以在Channel進行讀寫操作。這些Channel都會被註冊在Selector多路複用器上。Selector通過一個執行緒不停的輪詢這些Channel。找出已經準備就緒的Channel執行IO操作。
NIO 通過一個執行緒輪詢,實現千萬個客戶端的請求,這就是非阻塞NIO的特點。

AIO 設計原理:
AIO 並沒有採用NIO的多路複用器,而是使用非同步通道的概念。其read,write方法的返回型別都是Future物件。而Future模型是非同步的,其核心思想是:去主函式等待時間。

BIO NIO AIO 的詳細知識可以參考我的另外一篇文章 :Netty序章之BIO NIO AIO演變

相關文章