TCP協議底層結構詳解

2021-10-25 15:59:54 字數 4163 閱讀 2617

我們知道,tcp 套接字的資料收發無邊界。伺服器端即使呼叫1次write函式傳輸40位元組的資料,客戶端也有可能通過4次read函式呼叫每次讀取10位元組。但此處也有一些疑問,伺服器端一-次性傳輸了40位元組,而客戶端居然可以緩慢地分批接收。客戶端接收10位元組後,剩下的30位元組在何處等候呢?是不是像飛機為等待著陸而在空中盤旋一樣,剩下30位元組也在網路中徘徊並等待接收呢?

實際上,write 函式呼叫後並非立即傳輸資料,read 函式呼叫後也並非馬上接收資料。更準確地說,如下圖所示,write函式呼叫瞬間,資料將移至輸出緩衝;read函式呼叫瞬間,從輸入緩衝讀取資料。

假如,下面兩台的輸入快取大小為50位元組,而我們輸出快取為60位元組。現在右邊的電腦要給左邊的電腦傳1000位元組的資料。

1) 首先右邊的電腦就會先寫入60位元組的資料到輸出緩衝區內,然後就按一定速度傳到右邊的電腦接收緩衝區也就是輸入緩衝,假入右邊的電腦要讀取500位元組的資料,它並不會一下就讀取到500位元組的資料,因為它的輸入快取最大為50位元組,所以它只能先讀取50位元組。而左邊的電腦讀取輸入快取和右邊的電腦寫入輸入快取都有一定時間。而這個時間差越小越好。

2)因為當右邊電腦的發現電腦輸入快取為空,那麼它就會繼續寫入60位元組的資料到輸出緩衝區內,然後根據tcp協議的低層設計 ,右邊電腦就會先詢問一下左邊電腦,它的輸入快取是否還有位置,如果有,那麼右邊電腦就會把資料傳輸到左邊電腦輸入快取區, 如果沒有位置了那麼他就會在那裡等待,然後隔一段時間進行上訴操作。如果左邊的read操作遠大與右邊的電腦write操作,那麼右邊電腦就會長時間處於等待,詢問狀態。

所以我們在設計伺服器的時候,常常會單獨使用乙個執行緒來進行read操作,把讀取到的資料儲存在使用者區快取,而使用者使用者區快取由於可以在堆內分配,記憶體比較大,由此來保證輸入快取大部分時間為空的狀態,從而提高傳輸效率。

1.三次握手建立連線;

2.開始通訊,進行資料交換;

3.四次揮手斷開連線;

【第一次握手】主機a∶"你好,主機b。我這兒有資料要傳給你,建立連線吧。"

【第二次握手】主機b∶"好的,我這邊己就緒。"

【第三次握手】主機a∶"謝謝你受理我的請求。"

簡單描述:

(1)首先客戶端a會給伺服器b傳送乙個請求連線的請求,然後伺服器b會根據自身情況來決定是否連線,

(2)如果可以連線,那麼伺服器b就會給戶端a乙個響應,如果客戶端a接收到了伺服器b的響應後就會與伺服器b建立連線,

(3)然後客戶端a就會給伺服器b乙個響應,告訴伺服器b我這裡準備就緒了,可以建立連線了,如果伺服器b接收到了客戶端a響應後就可以與客戶端a建立連線,最後兩者相互之間建立了連線,就可以進行通訊了。

這其中的具體訊息傳輸,我們可以看下圖。

首先:【第一次握手】

[syn] seq:1000, ack:-

該訊息中seq為1000,ack為空,而seq為1000的含義如下∶

主機a:「現傳遞的資料報序號為1000,如果接收無誤,請通知我向您傳遞1001號資料報(也就是第三次握手的的傳送的seq為1001)。「這是首次請求連線時使用的訊息,又稱syn。syn是synchronization的簡寫,表示收發資料前傳輸的同步訊息。

【第二次握手】

接下來主機b向a傳遞如下訊息∶[syn+ack]seq:2000, ack:1001

此時seq為2000,ack為1001,

seq為2000的含義如下–主機b∶"現傳遞的資料報序號為2000如果接收無誤,請通知我向您傳遞2001號資料報。」

注意:tcp連線過程中傳送資料報時需分配序號。在之前的序號1000的基礎上加1,也就是分配1001,簡單來說,需要ack對別人傳送的資料報做出處理。

所以ack:1001的含義如下–主機b∶"剛才傳輸的seq為1000的資料報接收無誤,現在請你傳遞seq為1001(上次客戶端傳輸的seq+1)的資料報。」

對主機a首次傳輸的資料報的確認訊息(ack:1001)和為主機b傳輸資料做準備的同步訊息(seq2000)擁綁傳送,因此,此種型別的訊息又稱syn+ack。至此,主機a確認了主機b準備就緒。

注意:收發資料前向資料報分配序號,並向對方通報此序號,這都是為防止資料丟失所做的準備。通過向資料報分配序號並確認,可以在資料丟失時馬上檢視並重傳丟失的資料報。因此,tcp可以保證可靠的資料傳輸。最後觀察主機a向主機b傳輸的訊息︰

【第三次握手】

[ack]seq:1001, ack:2001

此時該資料報傳遞如下訊息,

seq為1001的含義如下∶"現傳遞的資料報序號為1001(對應第二次握手的ack)如果接收無誤,請通知我向您傳遞1002號資料報(資料通訊的資料報)。"

ack:2001︰「主機a已正確收到傳輸的seq為2000的資料報,現在可以傳輸seq為2001的資料報。」

這樣就傳輸了新增ack:2001的ack訊息。至此,主機b確認了主機a準備就緒,所以此時主機a和主機b確認了彼此均就緒。

上面所講的過程抽象到生活中就相當於這樣乙個場景:

tcp三次握手好比在乙個夜高風黑的夜晚,你乙個人在小區裡散步,不遠處看見小區裡的一位漂亮妹子迎面而來,但是因為路燈有點暗等原因不能100%確認,所以要通過招手的方式來確定對方是否認識自己。

你首先【向妹子招手(syn)】,妹子看到你向自己招手後,向你點了點頭【擠出了乙個微笑(ack)】。你看到妹子微笑後確認了【妹子成功辨認出了自己(進入建立連線(established)狀態)】。

但是妹子有點不好意思,向四周看了一看,有沒有可能你是在看別人呢,她也需要確認一下。妹子也【向你招了招手(syn)】,你看到妹子向自己招手後知道對方是在尋求自己的確認,於是也【點了點頭擠出了微笑(ack)】,妹子【看到對方的微笑後確認了你就是在向自己打招呼進入(建立連線(established)狀態)】。

於是兩人加快腳步,走到一起,愉快的相互交談(進入tcp通訊的第二步)。

我們來回顧一下,這個過程中總共有四個動作,

1.你招手

2.妹子點頭微笑

3.妹子招手

4.你點頭微笑

這不是四次握手嗎?為什麼說是三次??

答案:如上圖,2+3(ayn+ack)動作是兩個動作的合併

揮手過程:

【第一次揮手】主機a∶"我希望斷開連線。"

【第二次揮手】主機b∶"哦,是嗎?請稍候。"

【第三次揮手】主機b∶"我也準備就緒,可以斷開連線。

【第四次揮手】"主機a︰「好的,謝謝合作。」

簡單描述:

假如主機a要與主機b斷開連線,

【第一次揮手】首先主機a會給主機b傳送請求斷開連線的訊息,

【第二次揮手】然後主機b對主機a傳送的訊息做出響應,表示已經收到了請求斷開連線的訊息,並向主機a傳送訊息,表示正在檢視是否可以斷開連線,此時主機b並沒有處於可以斷開連線狀態。

【第三次揮手】主機b繼續對主機a傳送的訊息做出響應,表示已經收到了請求斷開連線的訊息,並向主機a傳送訊息,表示準備好了,已斷開連線。

【第四次揮手】主機a對主機b傳送的【準備好了,已斷開連線】的訊息做出響應,斷開與主機b的連線。

抽象到上次的場景中就是:

假如你和妹紙聊了很長時間,然後有事要離開了。

我:「對不起,我媽叫我回家了,我想分開了。」

妹紙:「好的,請稍後,我給我媽打個**,確定一下能不能回家。」

妹紙:"我確定好了,可以回家,分開吧。

" 我:「好的,我走了」。

我們發現在斷開連線的過程中,傳送請求斷開的一方需要兩次等待,也就是第二,第三次揮手,比較耗時,所以我們在設計伺服器的時侯,比如遊戲伺服器,動則成千上百萬,在處理伺服器請求與客戶端斷開連線時一般使用執行緒單獨處理,而不再主程序進行處理。

詳解TCP協議

16位的源埠號 傳送源的埠號 16位的目標埠號 目標的埠號 32位的序號 互動的初始資料段,序號值由系統生成的隨機值 isn。後續的報文段的序號為isn 所攜帶資料在整個位元組流中的偏移量。特點 1 所有的報文段序號不重複。2 後續的報文段序號值比前面的大。32位的確認號 由接收段填充,其值為序列號...

TCP協議詳解

參考部落格 在可靠的tcp網路通訊中,客戶端和伺服器端通訊建立連線的過程可簡單表述為三次握手 建立連線的階段 和四次揮手 釋放連線階段 下圖是這兩個階段的乙個完整的表述 其狀態圖可以表示為,在tcp連線建立的時候,存在乙個如下的有限狀態機 在狀態轉化圖中,其中客戶端的狀態轉移用帶箭頭的粗實線表示,伺...

TCP協議詳解

首先tcp是一種可靠的面向位元組流的協議,流指的是流入到程序或從程序流出的位元組序列。tcp的可靠性主要是由其首部的複雜結構結合可靠性傳輸原理 比如停止等待協議 arq 協議實現,可以說,tcp的首部是tcp能可靠傳輸的必要保障,了解tcp的首部很有必要 1.tcp首部 2.可靠傳輸基本原理 停止等...