1. 程式人生 > >socket通訊之一:TCP/IP模型與socket

socket通訊之一:TCP/IP模型與socket

這段時間看了一些網路相關的東西,這裡做一個總結吧。參考了很多文章的內容,因為我本身是對著書並且參考網路資源在學習的,在最後會一一列出文章的地址。

這篇文章主要介紹TCP/IP的一些基本知識,後面幾篇繼續深入一點探究。

本篇主要包括下面這些知識:

  1. TCP/IP是什麼
  2. socket介紹
  3. socket通訊流程
  4. socket中TCP三次握手建立連線
  5. socket中TCP的四次揮手釋放連線

1.TCP/IP是什麼

首先看一個引出TCP/IP協議族的問題,網路之間的程序如何進行通訊?

在本地可以通過程序PID來唯一標識一個程序,但是在網路中這是行不通的。TCP/IP協議族幫我們解決了這個問題,網路層的“ip地址”可以唯一標識網路中的主機,而傳輸層的“協議+埠”可以唯一標識主機中的應用程式(程序)。這樣利用三元組(ip地址,協議,埠)就可以標識網路的程序了,網路中的程序通訊就可以利用這個標誌與其它程序進行互動。

上面的例子告訴我們TCP/IP是用來幹什麼的,即它是用來讓網路之間的程序通訊時使用的。那麼什麼是TCP/IP?TCP/IPTransmission 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中的函式如下圖:


也就是說客戶端和服務端的流程是這樣子的:

客戶端的流程如下:

  1. 建立套接字(socket)
  2. 向伺服器發出連線請求(connect)
  3. 和伺服器端進行通訊(send/recv)
  4. 關閉套接字


伺服器端的流程如下:

  1. 建立套接字(socket)
  2. 將套接字繫結到一個本地地址和埠上(bind)
  3. 將套接字設為監聽模式,準備接收客戶端請求(listen)
  4. 等待客戶請求到來;當請求到來後,接受連線請求,返回一個新的對應於此次連線的套接字(accept)
  5. 用返回的套接字和客戶端進行通訊(send/recv)
  6. 返回,等待另一個客戶請求。
  7. 關閉套接字。

上面就是編寫socket程式時客戶端和伺服器端的基本步驟,每一個socket程式的基本步驟都是上面那幾步。

4.socket中TCP三次握手建立連線

在TCP/IP協議中,TCP協議通過三次握手建立一個可靠的連線。


  1. 第一次握手:客戶端嘗試連線伺服器,向伺服器傳送syn包(同步序列編號Synchronize Sequence Numbers),syn=j,客戶端進入SYN_SEND狀態等待伺服器確認
  2. 第二次握手:伺服器接收客戶端syn包並確認(ack=j+1),同時向客戶端傳送一個SYN包(syn=k),即SYN+ACK包,此時伺服器進入SYN_RECV狀態
  3. 第三次握手:第三次握手:客戶端收到伺服器的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中的四次握手釋放連線的過程,請看下圖:


圖示過程如下:

  1. 某個應用程序首先呼叫close主動關閉連線,這時TCP傳送一個FIN M;
  2. 另一端接收到FIN M之後,執行被動關閉,對這個FIN進行確認。它的接收也作為檔案結束符傳遞給應用程序,因為FIN的接收意味著應用程序在相應的連線上再也接收不到額外資料;
  3. 一段時間之後,接收到檔案結束符的應用程序呼叫close關閉它的socket。這導致它的TCP也傳送一個FIN N;
  4. 接收到這個FIN的源傳送端TCP對它進行確認。

這樣每個方向上都有一個FIN和ACK。