socket通訊之一:TCP/IP模型與socket
這段時間看了一些網路相關的東西,這裡做一個總結吧。參考了很多文章的內容,因為我本身是對著書並且參考網路資源在學習的,在最後會一一列出文章的地址。
這篇文章主要介紹TCP/IP的一些基本知識,後面幾篇繼續深入一點探究。
本篇主要包括下面這些知識:
- TCP/IP是什麼
- socket介紹
- socket通訊流程
- socket中TCP三次握手建立連線
- socket中TCP的四次揮手釋放連線
1.TCP/IP是什麼
首先看一個引出TCP/IP協議族的問題,網路之間的程序如何進行通訊?
在本地可以通過程序PID來唯一標識一個程序,但是在網路中這是行不通的。TCP/IP協議族幫我們解決了這個問題,網路層的“ip地址”可以唯一標識網路中的主機,而傳輸層的“協議+埠”可以唯一標識主機中的應用程式(程序)。這樣利用三元組(ip地址,協議,埠)就可以標識網路的程序了,網路中的程序通訊就可以利用這個標誌與其它程序進行互動。
上面的例子告訴我們TCP/IP是用來幹什麼的,即它是用來讓網路之間的程序通訊時使用的。那麼什麼是TCP/IP?TCP/IP(Transmission Control Protocol/Internet Protocol)即傳輸控制協議/網間協議,是一個工業標準的協議集,它是為廣域網(WANs)設計的。它定義了主機如何連入因特網及資料如何在它們之間傳輸的標準。
從字面意思來看TCP/IP是TCP和IP協議的合稱,但實際上TCP/IP協議是指因特網整個TCP/IP協議族。不同於ISO模型的七個分層,TCP/IP協議參考模型把所有的TCP/IP系列協議歸類到四個抽象層中
應用層:TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet 等等
運輸層:TCP,UDP
網路層:IP,ICMP,IGMP
資料鏈路層:SLIP,CSLIP,PPP,MTU
每一抽象層建立在低一層提供的服務上,並且為高一層提供服務,看起來大概是這樣子的。
圖1
IOS參考模型和TCP/IP模型的對比:
圖2
看完上面的圖表,對TCP/IP協議族應該有了一個大概的瞭解,它是指涉及到通訊過程中的一系列的協議,包括網路介面處,網路層,傳輸層的協議。為什麼要將網路通訊劃分成這麼多層次呢?因為它比較複雜,如果只用一個層來實現整個通訊流程,那麼這個層次會非常複雜,既不利於維護,也不利於擴充套件。從軟體工程的角度來考慮這個問題就很好理解了。不得不說最開始設計TCP/IP的人真是天才啊,知道要分層很容易想到,但是如何分層又是一個大問題,最早的那批先輩們幫我們解決了這個問題。我們現在只需要學習各個分層的作用就可以了。
2.socket介紹
看完上面的圖1中TCP/IP的介紹,但是都沒有socket的影子,那麼它在哪兒呢?
圖3
首先必須明確socket不是某一層的協議,它是應用層與TCP/IP協議族通訊的中間軟體抽象層,它是一組程式設計介面(即API),在設計模式中,socket就是門面模式(又稱為外觀模式,Facade),它把複雜的TCP/IP協議族隱藏在Socket介面後面,對使用者來說,一組簡單的介面就是全部,讓socket去組織資料,以符合指定的協議。
socket起源於UNIX,在Unix一切皆檔案哲學的思想下,socket是一種"開啟—讀/寫—關閉"模式的實現,伺服器和客戶端各自維護一個"檔案",在建立連線開啟後,可以向自己檔案寫入內容供對方讀取或者讀取對方內容,通訊結束時關閉檔案。
3.socket通訊流程
socket是"開啟—讀/寫—關閉"模式的實現,以使用TCP協議通訊的socket為例,其互動流程大概是這樣子的
上面是文字描述,對應於socket api中的函式如下圖:
也就是說客戶端和服務端的流程是這樣子的:
客戶端的流程如下:
- 建立套接字(socket)
- 向伺服器發出連線請求(connect)
- 和伺服器端進行通訊(send/recv)
- 關閉套接字
伺服器端的流程如下:
- 建立套接字(socket)
- 將套接字繫結到一個本地地址和埠上(bind)
- 將套接字設為監聽模式,準備接收客戶端請求(listen)
- 等待客戶請求到來;當請求到來後,接受連線請求,返回一個新的對應於此次連線的套接字(accept)
- 用返回的套接字和客戶端進行通訊(send/recv)
- 返回,等待另一個客戶請求。
- 關閉套接字。
上面就是編寫socket程式時客戶端和伺服器端的基本步驟,每一個socket程式的基本步驟都是上面那幾步。
4.socket中TCP三次握手建立連線
在TCP/IP協議中,TCP協議通過三次握手建立一個可靠的連線。
- 第一次握手:客戶端嘗試連線伺服器,向伺服器傳送syn包(同步序列編號Synchronize Sequence Numbers),syn=j,客戶端進入SYN_SEND狀態等待伺服器確認
- 第二次握手:伺服器接收客戶端syn包並確認(ack=j+1),同時向客戶端傳送一個SYN包(syn=k),即SYN+ACK包,此時伺服器進入SYN_RECV狀態
- 第三次握手:第三次握手:客戶端收到伺服器的SYN+ACK包,向伺服器傳送確認包ACK(ack=k+1),此包傳送完畢,客戶端和伺服器進入ESTABLISHED狀態,完成三次握手
伺服器socket與客戶端socket建立連線的部分其實就是大名鼎鼎的三次握手。
從圖中可以看出,當客戶端呼叫connect時,觸發了連線請求,向伺服器傳送了SYN J包,這時connect進入阻塞狀態;伺服器監聽到連線請求,即收到SYN J包,呼叫accept函式接收請求向客戶端傳送SYN K ,ACK J+1,這時accept進入阻塞狀態;客戶端收到伺服器的SYN K ,ACK J+1之後,這時connect返回,並對SYN K進行確認;伺服器收到ACK K+1時,accept返回,至此三次握手完畢,連線建立。
故客戶端的connect在三次握手的第二個次返回,而伺服器端的accept在三次握手的第三次返回。
5.socket中TCP的四次揮手釋放連線
上面介紹了socket中TCP的三次握手建立過程,及其涉及的socket函式。現在我們介紹socket中的四次握手釋放連線的過程,請看下圖:
圖示過程如下:
- 某個應用程序首先呼叫close主動關閉連線,這時TCP傳送一個FIN M;
- 另一端接收到FIN M之後,執行被動關閉,對這個FIN進行確認。它的接收也作為檔案結束符傳遞給應用程序,因為FIN的接收意味著應用程序在相應的連線上再也接收不到額外資料;
- 一段時間之後,接收到檔案結束符的應用程序呼叫close關閉它的socket。這導致它的TCP也傳送一個FIN N;
- 接收到這個FIN的源傳送端TCP對它進行確認。
這樣每個方向上都有一個FIN和ACK。