1. 程式人生 > >TCP數據傳輸過程詳解

TCP數據傳輸過程詳解

握手 ron 布爾 位域 fcm 打開 數據段 2個 處理

在學習三次握手的時候,我們知道其中有seq、ack兩個序列號。

如果不仔細了解,那麽可能只知道發回去的時候要加一。

下文將著重介紹,關於序列號的傳輸過程。

最關鍵的一句話:序列號為當前端成功發送的數據位數,確認號為當前端成功接收到的數據位數,SYN標誌位和FIN標誌位也要占1位

轉自:http://blog.csdn.net/a19881029/article/details/38091243

原文見:http://packetlife.net/blog/2010/jun/7/understanding-tcp-sequence-acknowledgment-numbers/

如果你正在讀這篇文章,很可能你對TCP“非著名”的“三次握手”或者說“SYN,SYN/ACK,ACK”已經很熟悉了。不幸的是,對很多人來說,對TCP的學習就僅限於此了。盡管年代久遠,TCP仍是一個相當復雜並且值得研究的協議。這篇文章的目的是讓你能夠更加熟練的檢查Wireshark中的TCP序列號和確認號

在我們開始之前,確保在Wireshark中打開示例(請到作者原文中下載)並親自實踐一下

示例中僅包含一個單獨的HTTP請求,請求的流程是:web瀏覽器向web服務器請求一個單獨的圖片文件,服務器返回一個成功的響應(HTTP/1.1200 OK),響應中包含請求的文件。右鍵示例文件中任意一個TCP包並且選擇Follow TCP Stream就可在單獨的窗口查看原始的TCP流

技術分享

客戶端請求使用紅色顯示,服務端響應使用藍色顯示

技術分享

TCP三次握手(參見:http://blog.csdn.net/a19881029/article/details/30241561)

TCP在其協議頭中使用大量的標誌位或者說1位(bit)布爾域來控制連接狀態,我們最感興趣的3個標誌位如下:

SYN - 創建一個連接

FIN - 終結一個連接

ACK - 確認接收到的數據

就像我們看見的那樣,一個包中有可以設置多個標誌位

選擇Wireshark中的“包”1並且展開中間面板的TCP層解析,然後展開TCP頭中的標誌位域,這裏我們可以看見所有解析出來的TCP標誌位,需要註意的是,“包1”設置了SYN標誌位

技術分享

使用同樣的方式操作“包2”。可以看到"包2"設置了2個標誌位:ACK - 用來確認收到客戶端的SYN包,SYN - 用來表明服務端也希望建立TCP連接

技術分享

從客戶端發來的“包3”只設置了ACK標誌位。這3個包完成了最初的TCP3次握手

技術分享

序列號和確認號

TCP會話的每一端都包含一個32位(bit)的序列號,該序列號被用來跟蹤該端發送的數據量。每一個包中都包含序列號,在接收端則通過確認號用來通知發送端數據成功接收

當某個主機開啟一個TCP會話時,他的初始序列號是隨機的,可能是0和4,294,967,295之間的任意值,然而,像Wireshark這種工具,通常顯示的都是相對序列號/確認號,而不是實際序列號/確認號,相對序列號/確認號是和TCP會話的初始序列號相關聯的。這是很方便的,因為比起真實序列號/確認號,跟蹤更小的相對序列號/確認號會相對容易一些

比如,在“包1”中,最初的相對序列號的值是0,但是最下方面板中的ASCII碼顯示真實序列號的值是0xf61c6cbe,轉化為10進制為4129057982

如果想要關閉相對序列號/確認號,可以選擇Wireshark菜單欄中的 Edit -> Preferences ->protocols ->TCP,去掉Relative sequence number後面勾選框中的√即可

技術分享

需要註意的是,文章接下來的部分依然使用相對序列號/確認號

為了更好的理解在整個TCP會話期間,TCP序列號和確認號是如何工作的,我們可以使用Wireshark內置的繪制流功能,選擇菜單欄中的 Statistics ->Flow Graph...->TCP flow ->OK

技術分享

Wireshark會自動創建一個TCP流的圖形摘要

技術分享

每行代表一個單獨的TCP包,左邊列顯示時間,中間列顯示包的方向、TCP端口、段長度和設置的標誌位,右邊列以10進制的方式顯示相關序列號/確認號,在這裏選中任意行會高亮主窗口中該行所關聯的包

我們可以利用這個流圖更好的理解序列號和確認號是如何工作的

包1

TCP會話的每一端的序列號都從0開始,同樣的,確認號也從0開始,因為此時通話還未開始,沒有通話的另一端需要確認(我使用的Wireshark版本和原作者不同,Wireshark1.10.2中,包1不顯示確認號)

包2

服務端響應客戶端的請求,響應中附帶序列號0(由於這是服務端在該次TCP會話中發送的第一個包,所以序列號為0)和相對確認號1(表明服務端收到了客戶端發送的包1中的SYN)

需要註意的是,盡管客戶端沒有發送任何有效數據,確認號還是被加1,這是因為接收的包中包含SYN或FIN標誌位(並不會對有效數據的計數產生影響,因為含有SYN或FIN標誌位的包並不攜帶有效數據)

包3

和包2中一樣,客戶端使用確認號1響應服務端的序列號0,同時響應中也包含了客戶端自己的序列號(由於服務端發送的包中確認收到了客戶端發送的SYN,故客戶端的序列號由0變為1)

此時,通信的兩端的序列號都為1,通信兩端的序列號增1發生在所有TCP會話的建立過程中

包4

這是流中第一個攜帶有效數據的包(確切的說,是客戶端發送的HTTP請求),序列號依然為1,因為到上個包為止,還沒有發送任何數據,確認號也保持1不變,因為客戶端沒有從服務端接收到任何數據

需要註意的是,包中有效數據的長度為725字節

包5

當上層處理HTTP請求時,服務端發送該包來確認客戶端在包4中發來的數據,需要註意的是,確認號的值增加了725(725是包4中有效數據長度),變為726,簡單來說,服務端以此來告知客戶端端,目前為止,我總共收到了726字節的數據,服務端的序列號保持為1不變

包6

這個包標誌著服務端返回HTTP響應的開始,序列號依然為1,因為服務端在該包之前返回的包中都不帶有有效數據,該包帶有1448字節的有效數據

包7

由於上個數據包的發送,TCP客戶端的序列號增長至726,從服務端接收了1448字節的數據,客戶端的確認號由1增長至1449

在抓包文件的主體部分,我們可以看到上述過程的不斷的重復,客戶端的序列號一直是726,因為客戶端除了最初的725字節數據沒有再向服務端發送數據,服務端的序列號則與此相反,由於服務端不斷的發送HTTP響應,故其序列號一直在增長

序列號為當前端成功發送的數據位數,確認號為當前端成功接收的數據位數,SYN標誌位和FIN標誌位也要占1位

關閉連接

技術分享

包38

在確認了服務端發送過來的最後一個數據段之後,客戶端將處理整個HTTP響應並決定不需要進一步通信了。此時客戶端發送設置了FIN標誌位的包38,其確認號和之前的包37一樣

包39

服務端通過將確認號加1的方式回應客戶端期望關閉連接的請求(這裏和包2中確認SYN標誌位時所作的操作是一樣的),同時設置當前包的FIN標誌位

包40

客戶端發送最終序列號727,通過將確認號加1的方式確認服務端的FIN包

此時,通信雙方都終結了會話並且可以釋放用於維持會話所占用的資源

TCP數據傳輸過程詳解