以瀏覽器訪問網頁為例,觀察瀏覽網頁過程中建立tcp三次握手,傳輸數據,最后四次揮手過程中的TCP的序號和確認號的變化規則,從而理解序號和確認號的含義。 抓包工具還是wireshark。
首先開始抓包,然后打開瀏覽器,隨便訪問一些網頁或者打開圖片,然后關閉瀏覽器,之后停止抓包。過濾tcp流:
這樣一個建立會話,傳輸數據,關閉會話的完整過程就都被抓了下來。
我們清晰的看到前三個數據包是三次握手,后面四個是揮手關閉。中間的是傳輸數據的過程。
這樣看序列號和確認號的變化規律不是很友好,我們可以用wireshark的統計功能查看tcp會話詳細過程:
注意選擇“限制顯示過濾器”和流類型為tcp,結果瞬間就清晰了
下面我們就分析一下序列號和確認號的變化規律。
首先wireshark顯示的序列號是一個相對值,理論上這個值是一個四個字節的數據,總共有32位,那就是
0和4,294,967,295之間的任意值。
但是我們是為了分析ack和seq的變化規則,所以用相對值就很方便。
先說結論,a給b發tcp報文,確認號seq代表我發送這個報文的順序或者位置(之前發送了多少的數據),ack確認號的意思是,我之前收到b給我發送的數據量。
聽不懂沒關系,我們看一下實際的通信過程。
左邊172.16.189.53是客戶端,右邊221.194.182.35是服務端。首先看三次握手:
第一個SYN:客戶端給服務端發第一個包,seq默認是0,0代表是第一個包。
第二個SYN+ACK:服務端給客戶端回包seq也是0,是因為這也是服務端給客戶端發的第一個包。Ack=1說明,服務端收到了客戶端發的第一個包。
第三個ACK:seq=1說明這是客戶端給服務端發的第二個包,ack=1說明收到了服務端給客戶端發的包。
接下來就是數據傳輸了,這時候會傳輸真實大小的數據,seq和ack變化就會不太一樣:
第一個包:大小為517。seq依然為1,是因為之前沒有真實的發送過數據。ACK為1因為到目前位置從服務端收到的數據僅僅為之前的SYN+ACK。
也就是說單純的ack數據包是不會對seq和ack的變化產生影響的。
第二個包:服務端回的ack。Seq=1因為這是服務端發送的第二個有有意義的包(0+1),ack=518(517+1)說明到目前為止收到了客戶端發來了518大小的數據。
第三個包:服務端回的ack,長度1412。Seq=1,還是因為這是服務端發的第二個有意義的包,ack=518說明到目前為止收到了客戶發來了518大小的數據
第四個包:客戶端回ack,長度1412。Seq=1413,為上一個數據包的seq加上上一個數據包的長度(1+1412),ack518說明目前為止收到了客戶發來了518大小的數據。
第五個:PSH+ACK,長度1272。Seq=2825.上一個數據包的seq加上一個數據包長度(1413+1412),ack=518說明到目前為止收到了客戶發來了518大小的數據。
第六個:客戶端發的ack。Seq=518,上一個數據包(也就是圖上的第一個包)的seq加上這個包的長度(1+517),ack=4097說明到目前位置收到的數據長度為4097(1+1412+1412+1272)
后面數據交互的序列號和確認號的變化規律也是這么變化的。
下面看四次揮手;
第一個包,客戶端發FIN請求關閉會話。Seq=809說明之前發送了809字節數據量。ack說明之前收到了5003字節的數據量。
第二個包,服務端回復ack。seq說明之前發送了5003的數據量,ack=810說明之前收到了810字節的數據(上一個包seq=809+1)
第三個包seq沒變還是5003,因為第二個包是個單純 的ack,不算發送實際意義的數據。
第四個包客戶端發ack,seq=810,是在第一個包的seq=809基礎上+1,ack=5004是在第三個包seq=5003基礎上+1。
總結:
序列號的變化是上一個數據包再加上這個數據包的數據長度;如果上一個數據包不傳數據,只是建立連接或者關閉連接,那么序列號seq只是加1;如果數據包只是回復對端的ack,那么序列號不變
確認號是告訴對面到目前本端收到了多少數據量,同樣的,單純的ack不算做數據量。