前幾天發了一個朋友圈,發現暗戀已久的女生給我點了個贊,于是我當晚輾轉反側、徹夜未眠!想著妹子是不是對我有感覺呢?不然怎么會突然給我點贊呢?要不趁機表個白?
于是第二天我在心中模擬了多次表白的話語,連呼吸都反復練習,
到了晚上,我撥通了妹子的微信語音,還沒等對方開口我就按捺不住內心的想法,開始自說自話,一陣狂亂的表達…足足五分鐘一氣呵成,一切都是那么自然!
可是在我說完之后卻半天都沒有等到妹子的回應…過了好一會兒才聽到對方的聲音:“喂!喂!我這邊信號不好,你剛剛在說啥我一句都沒聽到,我在跟我男朋友逛街呢…”,
我掛斷了電話,我也對我這次失敗的表白進行了深度的總結!原因就是因為我沒有學好TCP!
如果我懂TCP,那我在表白之前至少要先問一句“在嗎?”!先建立可靠的連接,確保連接正常才能開始表白!
如果我懂TCP,那我在我說話的程序中需要對方不斷的確認,這樣才能保證我說的每一句話對方都能聽到!這樣我才能表白成功!
所以一切都是因為我沒有學好TCP,于是我走進了圖書館…
我們先來看下TCP的定義:
TCP全稱為Transmission Control Protocol(傳輸控制協議),是一種面向連接的、可靠的、基于位元組流的傳輸層通信協議,TCP是為了在不可靠的互聯網路上提供可靠的端到端位元組流而專門設計的一個傳輸協議,
這里面每一個字我們都認識,但是連在一塊就不是那么好理解了!那我們就提煉一些關鍵的詞理解TCP的實作原理!
傳輸層
我們先講傳輸層,因為可以從比較高的層面去看TCP,我們先看下經典的OSI七層網路參考模型:

?當我們需要在網路上進行資料交換的時候,就需要經過這么幾層,每一層都有相關落地的實作,可能我們平時在說到傳輸層的時候自然而然的就想到的TCP,但是TCP只是傳輸層的一種實作,其他比較常見的傳輸層協議還有UDP等!
抓個包來看看,讓這幾層更加具象!本文中所有的包都是通過postman發送請求,然后用wireShark來抓的!我們在postman中輸入的域名,然后發送請求,wireshark就能抓到資料包了,

圖上已經標明每一層與抓到的資料包對應的關系了!咦!我們上面不是說的7層網路參考模型么?為什么資料包只有5層呢?注意參考二字,7層模型是一個理論模型,實際的網路中往往都把應用層、會話層、表示層統為應用層!
什么是協議?
說到協議,就是雙方共同遵守的一種約定!比如我寫的這篇文章里,你能夠看懂我寫的每一個字并明白我的意思,那就是因為我們都遵循了漢語的語法,這本身也就是一種協議,還有比如我們寫代碼就必須按照規定的語法進行撰寫,這樣編譯器才能進行正確編譯,
在計算機網路中也有很多協議,比如常見的應用層協議http、ftp、dns協議等等,常見的傳輸層協議有TCP、UDP等等…
其實這些協議都是發送方和接收方都在遵循的一種規范,如果我們遵循了其規范,也能成為協議的實作者,比如自己寫一個web服務器處理用戶請求,甚至我們還能自己規定一套協議,供別人使用!
TCP頭部格式
我們前面說了協議的定義,那TCP協議肯定也有一定的規范咯!這樣通信雙方才能識別對方的資料報文,進行資料交換,我們先看下TCP的報文格式

TCP報文包含資料頭和資料體,頭部有5行的固定長度以及1行可變長度!圖上前面5行就是固定長度!固定長度的每一行占有4個位元組(32位),因此頭部固定長度就為5*4=20個位元組!
面向連接怎么理解
從我表白失敗的例子就能看到,我還未確保連接的正常就開始表白,導致我說完了對方卻因為信號不好沒有聽到,如果我事先確保連接正常,就不會出現這樣的情況了!我們前面說了TCP是面向連接的,那TCP是怎么面向連接的呢?
三次握手交代了什么?
沒錯,都是從握手開始!我們都知道,tcp建立連接需要經過三次握手,那每次握手都交代了什么呢?如果只進行兩次握手行不行?我們先看一個電話接通的場景:
|
A:你好,你能聽到嗎? B:我能聽到,你能聽到嗎? A:我也能聽到, |
在正式通話之前,為了確保通話的可靠,往往都需要經過上面的三次對話進行確認,那這三次對話是必須的嗎?每一次對話的必要性又是什么呢?
|
A:你好,你能聽到嗎?(讓B知道A能說話) B:我能聽到,你能聽到嗎?(讓A知道B能聽到,且能說話) A:我也能聽到,(讓B知道A能聽到) |
只有經過三次的對話,才能確認自己的聲音能被對方聽到且能聽到對方的聲音,這也才能開展后續的對話,這里我們就不得不祭出經典的三次握手圖了:

我們依然發送請求,下面為三次握手的包:

?在info那一欄,我們很明顯的能看到發送的資料包頭部有我們上面說到的那些標志位,還有Seq、Ack等頭部資訊,還有Win、MSS等頭部選項資料!因此三次握手不僅僅是單純建立連接,還會協商一些引數!
當我滑鼠選擇某一行時,如果這個資料包包含了對某個資料包的確認(也就是有ACK的標記),就能在對應的資料包的No列上面看到一個小勾勾,比如上面圖中我滑鼠選擇的是第三次握手的資料包,在第二次握手的資料包前面就有個小勾勾,
為什么握手只需要三次而揮手需要四次?
通過三次握手,雙方就建立了一個可靠的連接,就能進行資料的傳輸了!當資料傳輸完成,就得將連接關閉,因為連接也是一種資源!連接的關閉需要經過四次揮手!
為什么握手可以三次完成,但是揮手卻需要四次呢?我偏要三次行不行?其實也沒啥不可以的!比如下面的對話場景:
|
A:我說完了,你說完就掛電話吧! B:好嘞,我也說完了,可以掛電話了! A:好嘞,拜拜, 掛斷…… |
這樣三次對話就可以實作揮手了,但是在實際的網路中,當我發出一個請求的時候,可能服務器的回應體比較大,需要較長時間的傳輸!所以當客戶端主動發起斷開請求的時候,服務器先回應一個確認,等所有資料傳輸完畢后再發送服務器斷開的請求,
|
A:我說完了,你說完就掛電話吧! B:好嘞… B:…… B:我也說完了,可以掛電話了 A:好嘞,拜拜 掛斷…… |
所以大部分情況下都需要進行四次揮手!但是,在我個人的抓包實踐中,也會有三次揮手就能完成斷開連接的情況,
這里我們又不得不祭出經典的四次揮手圖了:

我們看上面發送請求的揮手資料包:

?
可能大家在抓包的時候不能立馬看到四次揮手的資料包!那是因為在HTTP1.1及之后,默認都開啟了長連接!
也就是在一次請求之后,建立的連接并不會立馬關閉,而是供后續的其他請求繼續使用,以減少每次重新建立連接的資源消耗!
如果想發出請求后立馬能抓到四次揮手的資料包,可以設定Http的頭部Connection:close,這樣每次發送請求都能看到完整的三次握手四次揮手的程序啦!
最后,不管你是轉行也好,初學也罷,進階也可,如果你想學編程~
——【值得關注】我的C/C++編程學習交流俱樂部!——
涉及:C語言、C++、windows編程、網路編程、QT界面開發、Linux編程、游戲編程、黑客等等......
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/230136.html
標籤:C
上一篇:C++基礎知識篇:C++ 判斷
