「您好,我是 TCP
服務的實習生,剛培訓完,請問您就是 TCP
老司機嗎?」 瀏覽器
正坐在辦公室清閒喝着咖啡的我,差點一口噴出來,「哦哦,行,你終於來啦,看來幾天前的資源申請經過了啊,老司機?」服務器
「瀏覽器老大這麼叫你的,說你厲害,靠譜的很。」網絡
「好吧,既然來了,趕忙準備準備!這你的工做臺。」 我放下手中的咖啡,走到了一個靠窗的工做臺,指了指。工具
「好嘞。」 說着,剛來的小夥子走了過來。code
「好多工具啊,這個通道是什麼,這兒還有個鍾?都怎麼用呀?」 小夥子滿臉好奇的問道。資源
「這樣吧,從左到右,我一一給你說說。」打包
「首先,最左邊呢,是個通道,這裏會蹦出應用層須要咱們發送的數據。最多見的就是 HTTP
那小子的報文了。」循環
「瞭解,咱們的工做就是發送應用層的數據。原來不須要咱們本身去拿啊!」請求
「旁邊呢就是掃描機,你須要根據實際狀況把數據進行掃描,掃描機會把數據分塊,按序號,放在旁邊這個盒子裏。」通信
「嗯嗯,這個我清楚,數據塊大小須要根據實時的網絡狀況肯定。」
「不錯。這小夥子腦子還挺靈光。看來培訓的不錯」 我心中暗暗贊到。
「再往右,你看到這又是一個通道,這個通道就是咱們和服務器進行溝通的通道了。通道旁是兩個計數器,分別用來記錄咱們的序號和服務器序號,這個會自動加,你不用操做。就叫 1
號計數器和 2
號計數器吧,等下會用到。」
「好的,1
號計數器其實就是報文中的序號?」
「嗯嗯,不錯,用的時候看一眼就行,在計數器旁邊有幾個按鈕,我給你說說。這裏最好記一下。」
「嗯嗯」 說着小夥子拿出了筆記本開始記錄。
我指了指標着 SYN
的按鈕,說道:「這個是請求鏈接按鈕,也就是通知服務器,咱們想發數據給他。」
說着,最左側的通道忽然一閃,蹦出了一個 HTTP
服務打包好的包裹,剛來的小兄弟顯的有點慌亂,嚥了一口氣。
「恰好,那我就那這給給你作一下演示吧。」 說着,我站到了工做臺正中。
「嗯。」 小兄弟緊張的說不出話來。
「首先呢,按一下 SYN
按鈕,請求發送數據。」 1
號計數器跳了一下,由本來的 0
跳到了 1
。「按下這個按鈕工做臺會發送一個請求鏈接報文,相信報文的內容你應該清楚吧?」 我問道。
「SYN
爲 1
,序號爲 0
。」 看了一眼 1
號計數器,小夥子自信的答道。
「嗯,不錯!」 不一會計數器旁的通道蹦出了一段報文,2
號計數器直接由 0
跳到了 11
。
「讓咱們來看看,都有什麼,你看這裏。」 我指了指報文中的 ACK
,小夥子也靠了過來。
「ACK
等於 1
,說明服務器接受了咱們的鏈接請求,對吧?」 小夥子說道。
「是的,那咱們創建鏈接?」 我露出了狡猾的笑容。
「還須要覈對 確認序號
吧?」 小夥子有點困惑。
「爲何?」 我反問道。
「確保鏈接的準確性。老師說過,網絡是一個複雜的環境,會出現報文滯留的狀況,所以 TCP
鏈接兩端規定,在獲得請求鏈接時,須要將 確認序號
置爲請求序號加 1
。那麼如今咱們應該還要覈對 確認序號
與 1
號計數器的值!」 小夥子轉眼看向 1
號計數器,「咦,怎麼同樣?應該是差 1
的啊?」
「你忘了,在你按下 SYN
按鈕時,1
號計數器已經跳了一下嗎?」
「哦 ~」 小夥子恍然大悟,「那是應該相等,這個也太好用了吧!得記一下!」
「唰唰唰」 一旁發出鉛筆摩擦紙面的聲響,「有我剛來的樣子」 我不經感嘆道。
「接着,你看 SYN
字段爲 1
,說明服務器請求鏈接,TCP
是一個穩定的鏈接,雙向數據的通道,須要雙方都確認鏈接狀態,這點我不須要特殊說明吧?」
「嗯嗯,在學校老師說過。」
「那好,爲了確保鏈接的正確性,咱們須要和服務器作相同的操做,把序號加 1
後,放在確認序號內,服務器返回的序號是 10
咱們返回 11
就行。但這些不須要你進行實際的報文生成,在你肯定能夠創建鏈接的狀況下,按一下標着 ACK
按鈕就行。」 說着我按下了 ACK
按鈕。「如今三次握手結束,鏈接通道成功生成。咱們開始傳輸數據,剩下還有幾個按鈕用到的時候在說。」
「那個,我想問一下,我知道 TCP
是個雙向數據通道,但若是咱們不確認創建鏈接,直接發送數據應該也沒問題吧?咱們和服務器都已經發送了一次請求,而且都收到了,爲何還要確認一下呢?」 小夥子如有所思道。
「既然是雙向數據通道,那麼通道的兩端都應該清楚本身和對方的發送和接收的能力,對吧?」
「固然!否則通道是不穩定的。」
「那你想一想,在前兩次通訊過程當中,雙方都知道了哪些狀況?」
「第一次咱們發報文,第二次服務器返回報文咱們接收到,那咱們就知道了咱們有能力發送和接收,服務器也有能力接收和發送。」
「那服務器呢?」
「服務器的話,應該知道了他本身有能力接收,知道咱們有能力發送,他本身卻不清楚他能不能發送,也不知道咱們是否能接收!由於咱們還沒回復他。」
「所以呢,三次通訊(握手)讓雙方都知道了雙方都有發送與接收的能力,這對於一個雙向數據通道來講相當重要。」 我解釋道。
「嗯嗯,我記一下。」 又是一陣 「唰唰唰」 的聲音。
「已經創建了通道,那接下來就簡單了。」 我拿起 HTTP
扔過來的數據,說道:「咱們看看咱們一次能發送的數據包大小,在這兒。」 我指了指工做臺最右側的屏幕,屏幕上顯示着一連串的信息,「這些就是系統參數,這個就是咱們網絡所能承受的最大發送量。」
「嗯,一次能夠發送 1100
字節。」 小夥子邊看邊說道。
「嗯,不錯。那咱們就將數據按 1000
來切割吧,剩必定空間個報文頭部使用。」 說着我啓動一遍的掃描機,設定爲 1000
,丟進 HTTP
的數據,一旁的盒子出現排好序的數據塊。
「好神奇啊,學校裏都咱們本身切的。」 小夥子雙眼中冒着金光。
「接下來發生報文就行了。」
「好的,我來拼接數據,源端口:5800
,目標端口:80
,序號:1
,數據偏移:20
,標誌位:無特殊狀況,窗口大小:3
,校驗和:...」 小夥子忽然嘰裏咕嚕一堆,嚇了我一跳。
「不須要這麼麻煩,源端口,目標端口,在工做臺接收到應用層數據後,就能生成,至於序號和偏移量,你也不用關心啦,我來演示一遍,看好。」
我瞧了一眼服務器先前返回的報文,得知窗口爲 3
,拿起盒子裏的數據就往按鈕旁的通道里丟,一連丟了 3
個。1
號計數器也連續跳了 3
下,由 1
跳到了 1001
,在由 1001
跳到了 2001
,最終定格在 3001
。
「好了,接下來就等服務器響應了。」
「這就行了?」 小夥子明顯有點不敢相信。
「對啊,好了!等服務器確認就行。」 我有點得意。「工做臺會幫咱們把數據打包生成報文,這個工做臺但是個人專利!」
「哇塞,老司機就是厲害!比學校裏高級多了。」 小夥子雙眼中再次亮起金光。
沒過多久,2
號計數器連跳 3
次,噠噠噠,通道里蹦出 3
個服務器返回的報文,內容都爲:請求完成,須要下一份數據。
我拿起盒子裏的下 3
塊,往通道里扔。1
號計數器噠噠噠,又連着跳了 3
次。如此循環往復了十幾回,數據終於發完。
「今天的網不錯誒,沒有重發的狀況出現。如今咱們發完了,只須要等待服務器發送數據就好了。」
大概過了 10ms
,通道內陸陸續續開始蹦出報文,我剛想上手,一旁小夥子一把把報文攬走,「這個我熟,我來吧!」
獲取報文數據,按照序號排好,一頓操做還挺溜。
噠噠噠,2
號計數器不斷的跳動,定格在 50001
上。
「好如今數據也接收完畢了,須要進行單向關閉。如何進行關閉?」 我想考考小夥子的能力。
「發送報文,將 FIN
置爲 1
,序號爲 43001
。」 小夥子瞧了一眼 1
號計數器說道:「而後等服務器返回確認就行了,哦,對爲了應付網絡滯留狀況出現,須要覈對 確認序號
。」
「不錯,但在這...」 我話還沒說完,小夥子興奮的說道:「是否是按那個 FIN
按鈕就行了?」
「嗯,對!咱們只須要覈對 確認序號
就行了。你來操做吧 ~」 看着一臉興奮的小夥子,我中止了手中的操做。
「好的。」 說着,小夥子按下了 FIN
按鈕。1
號計數器跳了一下,定格在 43002
。不一會通道里蹦出了報文,確認序號與 1
好計數器一致,都爲 43002
。
「如今單向關閉成功,等待服務器請求關閉。」 小夥子一副訓練有素的樣子。
「嗯,不錯,接下來就等待服務器最終肯定關閉了。」 我拿起一旁的咖啡,慢悠悠的說道:「那你知道爲何這是單向關閉?」
「由於只有咱們這邊確認把數據都已經發送完畢啦 ~ 沒準服務器還有數據給咱們呢 ~ 」
「嗯,不錯。」 我拿起咖啡喝了一口,不經感慨道:「後繼有人了啊!」
「老大,服務器發出關閉請求了,你看。」 小夥子拿起一個報文,對我說道。
「我想你應該知道怎麼作了吧?」
「嗯嗯,按 ACK
按鈕就行了,這個和開啓鏈接確認是同一個操做,按您的智慧,應該是這樣。」 說着按下了 ACK
按鈕。
「嗯,這個彩虹屁真香,哦不,你真聰明!」
「哈哈」 咱們同時發出笑聲,「我和你說,那個 HTTP
服務部可不咋的,常常砸我,這不數據都好了,砸 TM
的。」
「duang
~」 通道一頭髮出一陣巨響,「TCP
大家沒完了是不?」