Linux 網路協議棧開發基礎篇(十二)—— 使用wireshark分析TCP/IP協議中TCP包頭的格式
摘要:
本文簡單介紹了TCP面向連線理論知識,詳細講述了TCP報文各個欄位含義,並從Wireshark俘獲分組中選取TCP連線建立相關報文段進行分析。
一、概述
TCP是面向連線的可靠傳輸協議,兩個程序互發資料之前需要建立連線,這裡的連線只不過是端系統中分配的一些快取和狀態變數,中間的分組交換機不維護任何連線狀態資訊。連線建立整個過程如下(即三次握手協議):
首先,客戶機發送一個特殊的TCP報文段;
其次,伺服器用另一個特殊的TCP報文段來響應;
最後,客戶機再用第三個特殊報文段作為響應。
圖1 三次握手協議示意圖[1]
二、TCP報文格式
2.1 概述
為了提供可靠的資料傳輸,TCP報文首部欄位有較多的欄位,TCP報文格式如下圖:
圖2 TCP報文格式
源和目標埠
用於多路複用/多路分解來自或送至上層應用的資料,可以這樣理解,埠用來標識同一臺計算機的不同程序。
序列號和確認號
這兩個欄位是TCP可靠傳輸服務的關鍵部分,序列號是該報文段首位元組的位元組流編號(TCP把資料看成是有序的位元組流,TCP隱式地對資料流的每個位元組進行編號)。這樣理解可能更直觀,當報文被分解成多個報文段時,序列號就是報文段首位元組在整個報文的偏移量。確定號指定下一個期待的位元組。TCP是全雙工的,假設從主機A接收到主機B的資料,則主機A填充進報文段的確認號是主機A期望從主機B收到的下一個位元組序號。還沒理清這兩者的關係?見下圖(三次握手):
圖3 正常情況下TCP連線建立過程
首部長度(4位)
因為選項是不定長的,這就需要標識整個首部欄位的長度(單位是32位字),即5+選項個數。4位,單位是32位字,所以首部最長是15*4=60位元組,即選項最長是40位元組(10個選項)。
標誌
URG
指示報文段裡存在著被髮送方的上層實體標記為”緊急”資料,當URG=1時,其後的緊急指標指示緊急資料在當前資料段中的位置(相對於當前序列號的位元組偏移量),TCP接收方必須通知上層實體。
ACK
當ACK=0時,表示該資料段不包含確認資訊,當ACK=1時,表示該報文段包括一個對已被成功接收報文段的確認。
PSH
當PSH=1時,接收方在收到資料後立即將資料交給上層,而不是直到整個緩衝區滿。
RST
用於重置一個已經混亂的連線(如主崩潰),也可用於拒絕一個無效的資料段或者拒絕一個連線請求。一般而言,如果你得到的資料段被設定了RST位,那說明你這一端有問題了。
SYN
用於建立連線過程,在連線請求中,SYN=1和ACK=0表示該資料段沒有使用捎帶的確認域,而連線應答捎帶一個確認,即SYN=1和ACK=1。
注:捎帶是指對客戶機到伺服器資料的確認被裝載在一個承載伺服器到客戶機的資料報文段中。
FIN
用於釋放一個連線,表示傳送方已經沒有資料要傳輸了。此時,接收方可能繼續接收資料,好在SYN和FIN資料段都有序列號,從而保證了這兩種資料段以正確順序被處理。
視窗大小
用於流控制(確保連線的任何一方都不會過快地傳送過量的分組而淹沒另一方),視窗大小指定了從被確認的位元組算起可以傳送多少個位元組。
校驗和
提供了額外可靠性,在計算檢驗和的時候,TCP的Checksum域設為0,如果資料域的位元組數為奇數,則資料域填補一個額外的0位元組。校驗和演算法:將所有的16位字按1的補碼形式累加起來,取累加結果的補碼。因此,當接收方執行同樣計算時(包括Checksum域),結果應該是0。
緊急指標
參考標誌欄位的URG位。
選項
選項部分是為了適合複雜網路環境和更好地服務於應用層設計的。TCP選項最長是40位元組。詳情見2.2。
資料
無任何資料的TCP段也是合法的,通常用於確認和控制資訊。
2.2 選項欄位[2]
TCP選項部分很好出現在已經建立連線的會話中,只要出現在TCP連線建立階段,即三次握手。TCP選項部分實際運用有以下幾種:
(1)最大報文傳輸段(MMS, Maximum Segment Size)
用於傳送發與接收方協商最大報文段長度(僅僅是淨荷資料,不包括TCP首部欄位)。TCP在三次握手中,每一方都會通告期望收到的MSS(MSS只出現在SYN資料包中),如果一方不接受另一方的MSS值,則使用預設的536位元組淨荷資料,即主機能夠接受20+536位元組的TCP報文段。
(2)視窗擴大選項(Window scaling)
TCP報文的視窗大小欄位佔16位,即最大值是65535,但隨著時延和頻寬比較大的通訊產生(如衛星通訊),需要更大的視窗滿足效能和吞吐率,這就是視窗擴大選項存在的意義。例子見參考資料[2]。
Windows scaling佔3個位元組,最後一個位元組是移位值(Shift count),即首部的視窗位數16向左移動,如移位值為14,則新的視窗最大值增大到65535*(2^14)。
視窗擴大選項是在TCP建立之初進行協商,如果已實現了視窗擴大,當不再需要擴大視窗時,傳送移位值=0就可以恢復到原視窗大小,即65535。
(3)選擇確認選項(SACK, Selective Acknowledgements)
考慮這樣情況,主機A傳送報文段12345,主機B收到135且報文無差錯,SACK用來確保只重傳缺少的報文段,而不是重傳所有報文段。
SACK選項需要2個功能位元組,一個用來指明使用SACK選項(SACK Permission),另一指明這個選項佔多少位元組。
那怎麼形容丟失的報文段2,說明2的左右邊界分別是1、3。TCP的資料報文是有字塊邊界的,而這種邊界是由序列號表示的。
最多能指明多少個位元組塊的邊界資訊呢?答案是4個。這是因為選項欄位最大是40位元組,去除2個功能位元組,序列號是32位即4位元組,並且需要左右邊界,所以(40-2)/8 = 4。
(4)時間戳選項(timestamps)
時間戳選項用來計算往返時間RTT,傳送方在傳送報文段時把當前時鐘的時間值放入時間戳欄位,接收方將該時間戳欄位的值複製到確認報文中,當接收方收到確認報文,對比確認報文的時間戳(等於傳送方傳送報文段的時間戳)和現在的時鐘,即可算出RTT。
時間戳選項還可用於防止迴繞序號PAWS。序列號只有32位,每2^32個序列號就會迴繞(想想環形佇列),採用時間戳選項很容易區分相同序列號的報文段。
(5)NOP(NO-Operation)
TCP的頭部必須是4位元組的倍數,而大多數選項不是4位元組倍數,不足的用NOP填充。除此之外,NOP也用於分割不同的選項資料,如視窗擴大選項和SACK之間使用NOP隔離(下面的例項將看到這一點)。
三、例項解析
3.1 概述
還是以訪問百度首頁為例,首先用DNS協議將URL解析成IP地址,接著在客戶機和伺服器間建立TCP連線,用Wireshark俘獲的分組如下圖:
圖4 Wireshark俘獲建立TCP連線分組
你一看會覺得有些奇怪,理論上應該是3個分組的,怎麼有6個分組?先不急,先把這6個報文收發示意圖作出來(結合時間和報文含義),如下:
圖5 TCP連線建立例項
從圖可知,連線建立伊始,客戶機發了兩個報文段,這也許是為了更快建立連線(假設有個請求報文段丟失,也不至於要等一段時間,重發報文)。接下來,以19、21、22(上圖紅色線條所示)分析TCP連線建立過程。
3.1 第一次握手19
Wireshark俘獲TCP連線第一次握手的報文段如下:
圖6 TCP連線第一次握手例項
這裡主要挑幾個欄位分析:
標誌欄位,SYN=1、ACK=0表示該資料段沒有使用捎帶的確認域。
最大報文段長度(MMS)1460是怎麼來的,鏈路層的乙太網物理特性決定資料幀長度為1500(即MTU,最大傳輸單元),1460=1500-20(IP首部長度)-20(TCP首部長度)。不要被該報文首部長度32位元組所迷惑,這只是建立連線過程。MSS與MTU關係見下圖[2]:
圖7 MSS與MTU關係
NOP欄位,可以作為不足4倍數字節填充,也可作為選項間分隔,該報文段出現了3個NOP,具體功能見下圖:
圖8 TCP報文NOP欄位
3.3 第二次握手21
伺服器響應客戶端TCP報文段,此時確認號為1了,SYN=1、ACK=1表明連線應答捎帶一個確認,Wireshark俘獲分組如下:
圖9 TCP連線第二次握手例項
為什麼MSS是1452而不是1460?這是因為使用PPPoE(Point-to-Point over Ethernet,可以使乙太網的主機通過一個簡單的橋接裝置連到一個無端的接入集中器上[3])撥號上網,PPoP首部是8個位元組,所以PPPoE的MTU是1492,MSS也就為1492-40=1452。
那麼,TCP連線建立後資料傳輸的MSS是多少呢,1460 or 1452 or 536 ?我的理解是預設值536,這樣理解對嗎?求指點!
3.4 第三次握手22
客戶機再次伺服器的報文段,此時序列號和確認號都為1,沒有選項欄位,Wireshark俘獲的分組資訊如下:
圖10 TCP連線第三次握手例項
值得注意的,因為視窗擴充套件大小協商未果,所以就不擴大視窗了,即視窗大小最大為65535。
如此,TCP連線建立:-)
相關推薦
Linux 網路協議棧開發基礎篇(十二)—— 使用wireshark分析TCP/IP協議中TCP包頭的格式
摘要: 本文簡單介紹了TCP面向連線理論知識,詳細講述了TCP報文各個欄位含義,並從Wireshark俘獲分組中選取TCP連線建立相關報文段進行分析。 一、概述 TCP是面向連線的可靠傳輸協議,兩個程序互發資料之前需要建立連線,這裡的連線只不過是端系統中分配的一些快
Linux 網路協議棧開發基礎篇(九)—— VID與PVID
一、PVID的作用及和VID的區別 PVID和VID經常出現於二、三層交換機裡,由於PVID和VID的設定不合理,造成VLAN劃分變得混亂。 PVID是交換機上的概念,說的是進入該埠的報文如果沒有打vlan id就按PVID的值打上,VID是報文
linux基礎篇(十二):Redhat7系統中rpm的相關操作與第三方軟體庫的搭建與共享
RPM RPM是Red-Hat Package Manager(RPM軟體包管理器)的縮寫,這一檔案格式名稱雖然打上了RedHat的標誌,但是其原始設計理念是開放式的,現在包括OpenLinux、S.u.S.E.以及Turbo Linux等Linux的分發版本都
python全棧開發基礎【第二十二篇】進程池和回調函數
enc 並發執行 exce 核數 exc 為什麽 .py bsp urn 一、數據共享 1.進程間的通信應該盡量避免共享數據的方式 2.進程間的數據是獨立的,可以借助隊列或管道實現通信,二者都是基於消息傳遞的。 雖然進程間數據獨立,但可以用過Manager實現數據共享,事實
linux基礎篇(十四):系統中的磁碟分割槽問題(一)
磁碟資訊查詢 fdisk -l fdisk命令用於觀察硬碟實體使用情況,也可對磁碟進行新增、刪除、轉換分割槽等操作 fdisk -l : 列出指定的外圍裝置的分割槽表狀況 cat /proc/partitions 查詢分割槽資訊,分割槽的大小,掛載點,剩餘空間
linux基礎篇(十五):系統中的磁碟分割槽問題(二)
對分割槽進行加密 操作 1:建立一個分割槽 partprobe 同步分割槽資訊 2:cryptsetup luksFormat /dev/vdb1 ###加密 YES 這裡必須輸入大寫的YES,此處小寫的yes系統不識別,應該是個bug 如果沒有crypt
linux基礎篇(十六):基於Redhat7系統中LVM的相關設定
什麼是LVM LVM是邏輯盤卷管理(Logical Volume Manager)的簡稱,它是Linux環境下對磁碟分割槽進行管理的一種機制,LVM是建立在硬碟和分割槽之上的一個邏輯層,來提高磁碟分割槽管理的靈活性。 LVM的工作原理其實很簡單,它就是通過將底層
Android開發學習筆記(十二)基礎UI控制元件之ImageView、CheckBox、RadioButton
一、ImageView:直接繼承自View,它的作用是在介面上顯示Drawable物件。 ImageView在佈局檔案(如main_activity.xml)中常用的屬性 有 scaleType ,s
Unity Editor 基礎篇(十一):結點編輯器基礎
轉自:http://mp.weixin.qq.com/s/CV_UTPMsWmz5w0gSOIPyFQ,請點選連線檢視原文,尊重樓主版權。 前言: 本文主要講解Unity編輯器中節點編輯器的建立使用。 知識點: 1.在自定義視窗內點選顯示選單項: 使用GenericM
python基礎學習(十二)
四種 b- zip int idl eight 正常 ppr 執行方法 模塊 前面有簡單介紹如何使用import從外部模塊獲取函數並且為自己的程序所用: >>> import math >>> math.sin(0) #sin為正
python基礎學習(十二)變數進階
目錄 1. 變數的引用 1.1 引用的概念 1.2 變數引用 的例項 1.3 函式的引數和返回值的傳遞 2. 可變和不可變型別 雜湊 (hash) 3. 區域性變數和全域性變數 3.1 區域性變數 3.2 全域性
Python3基礎之(十 二)函式預設引數
我們在定義函式時有時候有些引數在大部分情況下是相同的,一小部分情況下是不同的,所以為了提高函式的適用性,為了方便函式呼叫,也為了提供一些備選引數,我們可以將這些引數設定為預設引數,那麼該引數在函式呼叫過程中可以不需要明確給出。 一、基本使用 def function(para_1
【linux】Valgrind工具集詳解(十二):DHAT:動態堆分析器
一、概述 DHAT動態堆分析器。Massif(堆分析器)是在程式結束後輸出分析結果,而DHAT是實時輸出結果,所以叫做動態堆分析器。Massif只記錄堆記憶體的申請和釋放,DHAT還會分析堆空間的使用率、使用週期等資訊。 DHAT的功能:它首先記錄在堆上分配的塊,通過分析每次記憶體訪
Spring MVC使用篇(十二)—— 異常處理
1、綜述 在Web專案正式上線或者執行時,往往會出現一些不可預料的異常資訊。對於邏輯性或設計性問題,開發人員或者維護人員需要通過日誌,檢視異常資訊並排除異常;而對於使用者,則需要為其呈現出其可以理解的異常提示頁面,讓使用者有一個良好的使用體驗。所以異常的處
Linux程序間通訊(IPC)程式設計實踐(十二)Posix訊息佇列--基本API的使用
posix訊息佇列與system v訊息佇列的差別: (1)對posix訊息佇列的讀總是返回最高優先順序的最早訊息,對system v訊息佇列的讀則可以返回任意指定優先順序的訊息。 (2)當往一個空佇列放置一個訊息時,posix訊息佇列允許產生一個訊號或啟動一個執行緒,
Web開發來一發(十二)Kafka
1、Kafka簡介 Kafka是一個分散式釋出-訂閱訊息傳遞系統,常用於日誌服務。 Kafka基本結構包括Topic、Producer、Broker、Consumer: 1)Topic:特定型別的訊息流,訊息是位元組的有效負載; 2)Producer:能夠釋出訊息到話題的任何物件;
全棧JavaScript之路(十二)瞭解 Selector API
2008 年之前,瀏覽器中幾乎所有的DOM擴充套件都是專有的。此後,W3C 著手將一些已經成為事實標準的專有擴充套件標準化並寫入規範當中。 Selector API level 1 的核心是兩個方法: querySelector(), querySelectorAll(
SpringBoot開發詳解(十二) -- SpringBoot中執行定時任務
最近在專案中一直使用定時任務完成一些業務邏輯,比如天氣介面的資料獲取,定時傳送簡訊,郵件。以及商城中每天使用者的限額,定時自動收貨等等。定時器在專案中是我們常常會使用到的一個手段,今天我們就來看下在SpringBoot中如何整合定時任務。 定時任務在Sprin
從0開發3D引擎(十二):使用領域驅動設計,從最小3D程式中提煉引擎(第三部分)
[TOC] 大家好,本文根據領域驅動設計的成果,實現了init API。 # 上一篇博文 [從0開發3D引擎(十一):使用領域驅動設計,從最小3D程式中提煉引擎(第二部分)](https://www.cnblogs.com/chaogex/p/12411575.html) # 下一篇博文 [從0開發3D
python全棧開發基礎【第十八篇】網絡編程(socket)
回復 pro 解決 gettime connect 問題: 發送 lose post 一、網絡協議 客戶端/服務器架構 1.硬件C/S架構(打印機) 2.軟件C/S架構(互聯網中處處是C/S架構):B/S架構也是C/S架構的一種,B/S是瀏覽器/服務器 C/S架構與sock