TCP編程模型(TCP/IP網絡編程)【linux】(zzs)


使用TCP通信時,TCP協議要求必須要有一個服務器端
這一點是由TCP協議本身的特性決定的,只要你使用TCP協議來通信,就必須要有一個TCP服務器端。

TCP服務器的大概工作過程

(1)服務器會使用專門“文件描述符”來監聽客戶的“三次握手”,然後建立連接。
(2)一旦連接建立成功,服務器會分配一個專門的“通信文件描述符”,用於實現與該連接客戶的通信

由於建立連接時,雙方的TCP協議都已經記住了對方IP和端口,所以雙方正式通信時,TCP會自動使用記錄的IP和端口,我們不需要重新指定對方的IP和端口。

TCP編程模型

想要實現TCP通信,怎麼編程實現代碼

在編程模型裏面,必須要有一方是TCP服務器,另一方是TCP客戶。

服務器只有一個,但是客戶端有很多,不管客戶端有多少個,一個服務器同時爲多個客戶端服務,客戶端與服務器端的通信,都按照編程模型的描述來實現的。

圖解說明:
TCP編程模型

上面編程模型圖中,圖解種只畫了一個客戶端,但是一個客戶端,代表多個客戶端,服務器端只有一個。

服務器端

服務器端創建套接字文件

調用socket函數創建套接字文件,返回套接字文件描述符,套接字文件描述符專門用於監聽客戶連接。

服務器端綁定

將套接字文件,服務器IP,服務器端口綁定在一起,端口指的是服務器程序的端口號。綁定在一起的目的就是建立固定對應關係,及就是套接字文件使用固定的IP,使用固定的端口。客戶端主動向服務器端發起連接請求,所以服務器的IP和端口一定是固定的,而且是公開的。如果不固定,不公開,客戶端就無法主動發起連接請求。

通過bind函數的參數來指定套接字文件描述符,服務器IP,服務器端口號。

服務器端創建被動文件描述符

調用socket函數創建套接字文件,返回套的接字文件描述符是一個主動文件描述符,主動文件描述符不能用來監聽客戶連接。
建立客戶端與服務器端連接時,是由客戶端主動向服務器發起請求,服務器是一個被動的過程,調用listen函數,將套接字文件描述符變爲被動描述符,只有被動的文件描述符才能被動監聽客戶連接。

服務器端被動監聽

被動監聽客戶的握手請求,被動監聽及就是等,完成三次握手即連接成功,如果沒有客戶鏈接,上面accept函數是阻塞的,一旦有客戶連接將不再阻塞,連接成功後,返回一個通信文件描述符。
通信文件描述符專門用來實現服務器端與其中一個剛建立連接的客戶端之間的通信。

服務器端發送數據

接下來,服務器就可以使用accept函數返回的通信文件描述符向服務器端發送數據,發送數據時可以調用write函數,也可以調用send函數。調用這兩個函數的時候,只需要指定通信文件描述符,不需要指定IP和端口,因爲在建立連接的時候,服務器已經通過TCP自動記錄了客戶端的IP和端口。我們只需要使用文件描述符就會自動使用對應的客戶端IP和端口。

服務器端接收數據

從調用read函數和recv函數從客戶端使用通信文件描述符接收數據。

服務器端與客戶端斷開

當服務器端與服務器不需要通信的時候,需要進行四次揮手斷開連接,四次揮手可由任意一方發起,服務器端主動斷開連接,調用close(fd)或shutdown(fd)函數與某一個通信的客戶端斷開連接。服務器這裏使用的fd是通信文件描述符,不是監聽文件描述符。服務器端使用
通信文件描述符,斷開的是通信文件描述符與哪一個客戶端進行通信,那麼就斷開與對應客戶端的連接。

斷開的過程中,服務器端的TCP主動向客戶端的TCP發起斷開連接的請求,斷開連接時會四次揮手。四次揮手成功,斷開連接。

上面的編寫步驟是由TCP協議來決定,使用TCP協議進行通信就必須使用TCP編程模型來編寫服務器,否則無法使用TCP通信。

客戶端

客戶端創建套接字文件

調用socket函數返回skfd,創建套接字文件,返回套接字文件描述符。

客戶端發起連接

調用connect(skfd……)函數,connet函數參數還需要寫服務器的IP和端口,因爲向服務器發起連接請求,必須要有服務器端的IP和端口,客戶端才能知道向誰發起連接,主動向對應IP和端口的服務器發起握手請求,發起握手請求成功之後,客戶端TCP會自動記錄服務器端IP和端口。服務器端accept接受握手請求,也就是說客戶端connect函數對應的是服務器端的accept函數。三次握手由雙方TCP自動完成。三次握手OK,即連接成功,就可以正式進行通信。

客戶端發送數據

客戶端調用write函數和send函數向服務器端發送數據,服務器端通過read和recv函數接受數據。客戶端發送數據的時候也不需要指定服務器端的IP和端口,在建立連接的時候已經自動記錄了IP 和端口,所以只需要使用套接字文件描述符。客戶端直接使用skfd來通信。

客戶端接收數據

調用read(skfd)和recv(skfd)函數,接受服務器發送過來的數據,同樣的參數只需要文件描述符即可接受服務器端發送過來的數據。

客戶端斷開連接

客戶端斷開連接,調用close(skfd)函數或者shutdown(skfd)函數即可斷開連接。由客戶端向服務器端主動發起斷開連接的請求。調用函數之後,客戶端TCP協議會主動向服務器端TCP協議發起斷開連接的請求,四次揮手成功,斷開連接。

服務器是如何同時應對多客戶的通信呢?

多線程 和 多進程

圖解說明:
多進程多線程實現服務器是如何同時應對多客戶

服務器是主線程或者父進程,專門監聽客戶連接,請求連接並且連接成功,就返回一個專門用於通信的文件描述符,每當一個客戶機連接成功,就創建一個次線程或者子進程,把用於通信的文件描述符給次線程或者子進程,次線程或者子進程拿到對用通信的文件描述符之後,就專門負責與對應的客戶端進行通信。

以此類推,創建多個次線程或者子進程,來實現服務器端與多個客戶端之間的通信。對於服務器來說,次線程和子進程是併發運行的。所以可以同時服務多個客戶端。並且多個次線程和子進程不會干擾到主線程或者父進程的監聽。因爲主線程或者父進程與所有的次線程和子進程都是併發運行的,互不干擾。

多路io

主要使用seletc和poll機制。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章