總結TCP通信【linux】(zzza)

TCP通信分爲兩步

第一步:建立連接來提高通信的可靠性。建立連接時,服務器和客戶的TCP協議會自動記錄下對方ip和端口。

當然,能夠建立連接的前提是,服務器端綁定了固定的ip和端口,而且客戶端知道這個固定的ip和端口,只有這樣客戶端才知道向誰請求連接,否則都不知道和誰連接,更不要談連接成功了。

第二步:使用通信描述符直接收發數據,此時會自動使用TCP記錄的IP和端口。

爲了弄清楚TCP通信的具體過程,我們分三種情況來看。

TCP通信的具體過程

本機通信

圖解分析:
本機通信

客戶端端程序和服務器端程序都運行在同一臺主機上,進行本機通信。

服務器端調用bind函數綁定固定的ip和固定的端口,客戶端的端口是自動分配的,客戶端端口是變化的,每一次連接的時候客戶端的端口號都可能是不一樣的。由於是本機通信,所以本機ip是一樣的。

當然,ip也有可能不一樣,因爲會出現一臺計算機有多個ip的情況,但是一般情況下,同一臺主機的只有一個ip。

由於是本機通信,所以客戶端程序和服務器端程序公用同一個TCP/IP協議棧。

客戶端調用connect函數來主動發起連接請求。

客戶端調用connect函數的時候必須給定connect函數服務器固定的端口和固定的ip。

客戶端調用connect函數之後,connect函數會將包含服務器端的ip和端口的應用層數據包發送給TCP傳輸層, (這裏的TCP傳輸層可以理解爲客戶端的TCP傳輸層)TCP傳輸層就封裝傳輸層包頭然後把數據包發送給IP網絡層,IP網絡層繼續封包。

IP網絡層網絡層通過檢查發現源ip等於目標ip就知道進行的是本機通信,那麼到達IP網絡層之後就會直接返回,不會通過網絡層繼續向下發送數據,將數據包回發給TCP 傳輸層(這裏的TCP傳輸層可以理解爲服務器的TCP傳輸層)。

客戶端調用connect函數的目的爲了完成三次握手。

第一次TCP傳輸層把數據發送給IP網絡層,IP網絡層又把數據回發給TCP傳輸層,此時服務器端的accept函數並不會立即響應,因爲請求連接的時候有三次握手,第一次發送握手收據需要由客戶端connect函數啓動,三次握手是由TCP通信協議自動完成的。三次握手成功之後,表示客戶端和服務器連接成功。連接成功之後accept函數纔會有響應。在三次握手沒有完成之前,服務器端的accept函數是不會有響應的。

三次握手成功之後,服務器端會自動記錄客戶端和ip和端口,客戶端也會自動記錄服務器端的ip和端口。

如果三次握手失敗,服務器端的accpet函數不會有任何響應。客戶端的connect函數會錯誤返回並且提示客戶端連接失敗,客戶端就需要重新連接。

連接成功,服務器端accept函數返回通信文件描述符用於與客戶端進行通信,同時客戶端connetc函數調用成功之後繼續向下執行,然後客戶端和服務器端開始互相收發數據進行通信。

局域網內跨機通信

圖解說明:
局域網內跨機通信

客戶端計算機和服務器端計算機在同一個局域網裏面,也就是主機ip在同一個網段。
服務器端調用bind函數綁定固定的ip和端口,客戶端的ip和端口都是自動設置的。

同樣也是客戶端與服務器端先建立連接,然後進行通信。
首先客戶端調用connect 函數主動發起連接請求,發起連接請求之後, connect函數會將包含服務器端的ip和端口的應用層數據包發送給客戶端TCP傳輸層,客戶端TCP傳輸層繼續封裝傳輸層包頭然後把數據包發送給客戶端IP網絡層,客戶端IP網絡層繼續封包。

客戶端IP網絡層通過檢查發現源ip不等於目標ip就知道進行的不是本機通信,然後把客戶端IP網絡層封裝的數據包繼續發送給鏈路層,然後發送給交換機,交換機再發送給服務器端的網卡,(關於如何封裝各層數據包,如果通過客戶端網卡把數據發送給交換機,然後交換機把數據發送給服務器我們在計算機網絡系列博客中已經詳細進行說明。)數據到達服務器端TCP傳輸層之後第一次握手成功,第一次握手成功之後服務器端TCP通過提取客戶端的ip和端口給客戶端發送回答數據,然後繼續完成三次握手。

三次握手由TCP通信自動完成。

三次握手成功之後,客戶端會自動記錄服務器端的ip和端口,服務器端也會自動記錄客戶端的ip和端口。

三次握手成功之後,服務器端accept返回一個通信文件描述符進行通信,客戶端connect 函數調用成功之後使用套接字文件描述符進行通信,程序繼續運行,客戶端和服務器端開始進行通信。

三次握手的過程中,accept函數不會響應,只有當三次握手成功之後accept函數纔會響應並且返回通信文件描述符。

如果三次握手失敗了,服務器端accept函數不會響應,客戶端connect函數在三次握手失敗之後錯誤返回。

連接成功之後,客戶端和服務器端開始收發數據,在收發數據通信的過程中,對方在收到數據之後並不會立即把數據向上層傳遞,而是先回答對方,如果回答說數據是錯的,那麼對方就會重新發送數據,之後回答收到的數據是正確的,纔會繼續向上層提交數據。回答的過程由TCP通信自動完成。

數據過路由器,跨網通信

圖解說明:
過路由器,跨網通信

同樣的客戶端調用connect 函數發起連接請求,connect 函數封裝服務器的ip和端口。
這裏需要注意;connect 函數封裝的服務器端的ip一定是服務器所在路由器的公網ip,因爲跨網通信的過程當中涉及到net轉換,所以一定會使用公網ip。

Connect 函數把應用層數據包交給客戶端的TCP傳輸層,客戶端的TCP傳輸層再封裝之後交給客戶端的IP網絡層,客戶端的IP網絡層再封裝之後繼續向下交給鏈路層,鏈路層發送給網卡,網卡交給交換機,交換機交給路由器,然後進行net轉換,數據從內網發送到外網的時候,把源ip轉化爲公網ip。

數據經過路由器之後,源ip就從私網ip轉換爲公網ip,然後把數據發送給廣域網交換機,廣域網交換機把數據發送給和客戶端路由器的公網ip在同一個網段的路由器。

服務器只是路由器下面的某一臺計算機,所以要找到服務器所在的計算機就要再次進行net轉換,把數據的目標ip從公網ip轉換爲服務器的私網ip。然後通過服務器端所在的交換機把數據發送到服務器端的網卡,然後向上知道發送到服務器端的TCP傳輸層,第一次握手成功。

然後服務器端的TCP傳輸層開始回答,第一次發送給服務器端的數據裏面包含有客戶端的ip和端口,所以就能夠進行回答。只不過數據包裏面的ip是客戶端所在路由器的公網ip。所以服務器端在進行第二次握手回答的時候,通過客戶端所在路由器的公網ip進行回答。
數據一路返回,在服務器端所在的路由器時,通過net轉換將服務器端的私網ip轉化爲公網ip,在數據到達客戶端所在的路由器的時候,繼續進行net轉換。將目標ip從公網ip轉換爲客戶端的私網ip。然後將數據一路向上發送到客戶端的TCP傳輸層完成第二次握手。同樣的原理客戶端在進行回單繼續完成第三次握手。

三次握手成功之後連接成功,客戶端自動記錄服務器端的端口號和服務器端所在路由器的公網ip,服務器端也會自動記錄客戶端的端口號和客戶端所在路由器的公網ip。

三次握手連接成功之後開始互相收發數據,互相發送數據時把原始數據交給TCP傳輸層,然後傳輸層把自動記錄的ip和端口進行封包,然後發送給IP網絡層進行封包,然後向下發發送直到發送到對方的TCP傳輸層,對方的TCP傳輸層在接收到數據之後並不會直接向上發送,而是進行回答,只有回答當數據是正確的之後,纔會將數據繼續向上提交。如果回答數據是錯誤的,那麼對方就需要重新發送數據。

TCP服務器/客戶模式

對於TCP協議來說,只要你使用TCP協議,必然有一個服務器端,而其它的都是客戶端,這一點是由TCP協議本身的特性所決定的,而不是“應用程序”來決定的,所以使用TCP協議通信時,是天然的服務器/客戶模式。

也就是一個服務器端爲多個客戶端服務。

如果TCP客戶之間想要通信,TCP客戶之間無法直接通信。

在TCP的服務器/客戶模式下,只能通過服務器來中轉。

服務器爲了同時與衆多客戶進行通信,可以有三種方式:
(1)多線程
(2)多進程
(3)多路IO

這三種方式的實現,我們在後面博客中會詳細說明。

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