【Linux网络编程】TCP 和 UDP 数据报格式详解
TCP 報文格式
TCP(Transmission Control Protocol 傳輸控制協(xié)議)是一種面向連接的、可靠的、基于字節(jié)流的傳輸層通信協(xié)議。
TCP 報文段的報頭有 10 個必需的字段和 1 個可選字段。報頭至少為 20 字節(jié)。報頭后面的數(shù)據(jù)是可選項。
1)源端口(16位)
標(biāo)識發(fā)送報文的計算機(jī)端口或進(jìn)程。一個 TCP 報文段必須包括源端口號,使目的主機(jī)知道應(yīng)該向何處發(fā)送確認(rèn)報文。
2)目的端口(16位)
標(biāo)識接收報文的目的主機(jī)的端口或進(jìn)程。
3)?序號(也叫序列號)(32位)
用于標(biāo)識每個報文段,使目的主機(jī)可確認(rèn)已收到指定報文段中的數(shù)據(jù)。當(dāng)源主機(jī)用于多個報文段發(fā)送一個報文時,即使這些報文到達(dá)目的主機(jī)的順序不一樣,序列號也可以使目的主機(jī)按順序排列它們。
在 SYN 標(biāo)志未置位時,該字段指示了用戶數(shù)據(jù)區(qū)中第一個字節(jié)的序號;在 SYN 標(biāo)志置位時,該字段指示的是初始發(fā)送的序列號。
在建立連接時發(fā)送的第一個報文段中,雙方都提供一個初始序列號。TCP 標(biāo)準(zhǔn)推薦使用以 4ms 間隔遞增 1 的計數(shù)器值作為這個初始序列號的值。使用計數(shù)器可以防止連接關(guān)閉再重新連接時出現(xiàn)相同的序列號。
? ?
對于那些包含數(shù)據(jù)的報文段,報文段中第一個數(shù)據(jù)字節(jié)的數(shù)量就是初始序列號,其后數(shù)據(jù)字節(jié)按順序編號。如果源主機(jī)使用同樣的連接發(fā)送另一個報文段,那么這個報文段的序列號等于前一個報文段的序列號與前一個報文段中數(shù)據(jù)字節(jié)的數(shù)量之和。例如,假設(shè)源主機(jī)發(fā)送 3 個報文段,每個報文段有 100 字節(jié)的數(shù)據(jù),且第一個報文段的序列號是 1000,那么第二個報文段的序列號就是 1100(1000 + 100),第三個報文段的序列號就是 1200(1100 + 100)。
? ?
如果序列號增大至最大值將復(fù)位為 0。
4)確認(rèn)號(32位)
目的主機(jī)返回確認(rèn)號,使源主機(jī)知道某個或幾個報文段已被接收。如果 ACK 控制位被設(shè)置為 1,則該字段有效。確認(rèn)號等于順序接收到的最后一個報文段的序號加 1,這也是目的主機(jī)希望下次接收的報文段的序號值。返回確認(rèn)號后,計算機(jī)認(rèn)為已接收到小于該確認(rèn)號的所有數(shù)據(jù)。
例如,序列號等于前一個報文段的序列號與前一個報文段中數(shù)據(jù)字節(jié)的數(shù)量之和。例如,假設(shè)源主機(jī)發(fā)送 3 個報文段,每個報文段有 100 字節(jié)的數(shù)據(jù),且第一個報文段的序列號是 1000,那么接收到第一個報文段后,目的主機(jī)返回含確認(rèn)號1100 的報頭。接收到第二個報文段(其序號為 1100 )后,目的主機(jī)返回確認(rèn)號 1200。接收到第三個報文段后,目的主機(jī)返回確認(rèn)號 1300 。
目的主機(jī)不一定在每次接收到報文段后都返回確認(rèn)號。在上面的例子中,目的主機(jī)可能等到所有 3 個報文段都收到后,再返回一個含確認(rèn)號 1300 的報文段,表示已接收到全部 1200 字節(jié)的數(shù)據(jù)。但是如果目的主機(jī)再發(fā)回確認(rèn)號之前等待時間過長,源主機(jī)會認(rèn)為數(shù)據(jù)沒有到達(dá)目的主機(jī),并自動重發(fā)。
上面的例子中,如果目的主機(jī)接收到了報文段號為 1000 的第一個報文段以及報文段號為 1200 的最后一個報文段,則可返回確認(rèn)號 1100,但是再返回確認(rèn)號 1300 之前,應(yīng)該等待報文段號為 1100 的中間報文段。
5)?數(shù)據(jù)偏移(首部長度)(4位)
TCP 報文段的數(shù)據(jù)起始處距離 TCP 報文段的起始處有多遠(yuǎn),即首部長度。由于 TCP 報頭的長度隨 TCP 選項字段內(nèi)容的不同而變化,因此報頭中包含一個指定報頭字段的字段。該字段以 32 比特為單位,所以報頭長度一定是 32 比特的整數(shù)倍,有時需要在報頭末尾補(bǔ) 0 。如果報頭沒有 TCP 選項字段,則報頭長度值為 5 ,表示報頭一個有 160 比特,即 20 字節(jié)。
6)保留位(6位)
由跟在數(shù)據(jù)偏移字段后的 6 位構(gòu)成,?全部為 0 。
7)控制位(6位)
緊急 URG:此位置 1,表明緊急指針字段有效,它告訴系統(tǒng)此報文段中有緊急數(shù)據(jù),應(yīng)盡快傳送。
確認(rèn) ACK:僅當(dāng) ACK = 1 時確認(rèn)號字段才有效,TCP 規(guī)定,在連接建立后所有傳達(dá)的報文段都必須把 ACK 置 1。
推送 PSH:當(dāng)兩個應(yīng)用進(jìn)程進(jìn)行交互式的通信時,有時在一端的應(yīng)用進(jìn)程希望在鍵入一個命令后立即就能夠收到對方的響應(yīng)。在這種情況下,TCP 就可以使用推送(push)操作,這時,發(fā)送方 TCP 把 PSH 置 1 ,并立即創(chuàng)建一個報文段發(fā)送出去,接收方收到 PSH = 1 的報文段,就盡快地(即“推送”向前)交付給接收應(yīng)用進(jìn)程,而不再等到整個緩存都填滿后再向上交付。
復(fù)位 RST:用于復(fù)位相應(yīng)的 TCP 連接
同步 SYN:僅在三次握手建立 TCP 連接時有效。當(dāng) SYN = 1 而 ACK = 0 時,表明這是一個連接請求報文段,對方若同意建立連接,則應(yīng)在相應(yīng)的報文段中使用 SYN = 1 和 ACK = 1。因此,SYN 置 1 就表示這是一個連接請求或連接接受報文。
終止 FIN:用來釋放一個連接。當(dāng) FIN = 1 時,表明此報文段的發(fā)送方的數(shù)據(jù)已經(jīng)發(fā)送完畢,并要求釋放運(yùn)輸連接。
8)窗口(16位)
此字段用來進(jìn)行流量控制,這個值是本機(jī)期望一次接收的字節(jié)數(shù),即發(fā)送數(shù)據(jù)的窗口大小。告訴對方在不等待確認(rèn)的情況下,可以發(fā)來多大的數(shù)據(jù)。這里表示的最大長度是2^16 - 1 = 65535,如需要使用更大的窗口大小,需要使用選項中的窗口擴(kuò)大因子選項。
指發(fā)送本報文段的一方的接收窗口(而不是自己的發(fā)送窗口)。
9)校驗和(16位)
源主機(jī)和目的主機(jī)根據(jù) TCP 報文段以及偽報頭的內(nèi)容計算校驗和。在偽報頭中存放著來自 IP 報頭以及 TCP 報文段長度信息。與 UDP 一樣,偽報頭并不在網(wǎng)絡(luò)中傳輸,并且在校驗和中包含偽報頭的目的是為了防止目的主機(jī)錯誤地接收存在路由的錯誤數(shù)據(jù)報。
偽首部,又稱為偽包頭(Pseudo Header):是指在 TCP 的分段或 UDP 的數(shù)據(jù)報格式中,在數(shù)據(jù)報首部前面增加源 IP 地址、目的 IP 地址、IP 分組的協(xié)議字段、TCP 或 UDP 數(shù)據(jù)報的總長度等共12字節(jié),所構(gòu)成的擴(kuò)展首部結(jié)構(gòu)。此偽首部是一個臨時的結(jié)構(gòu),它既不向上也不向下傳遞,僅僅只是為了保證可以校驗套接字的正確性。
10)緊急指針(16位)
僅在 URG = 1 時才有意義,它指出本報文段中的緊急數(shù)據(jù)的字節(jié)數(shù)(緊急數(shù)據(jù)結(jié)束后就是普通數(shù)據(jù)),即指出了緊急數(shù)據(jù)的末尾在報文中的位置,注意:即使窗口為零時也可發(fā)送緊急數(shù)據(jù)。
如果 URG 為 1 ,則緊急指針標(biāo)志著緊急數(shù)據(jù)的結(jié)束。其值是緊急數(shù)據(jù)最后 1 字節(jié)的序號,表示報文段序號的偏移量。例如,如果報文段的序號是 1000,前 8 個字節(jié)都是緊急數(shù)據(jù),那么緊急指針就是 8 。緊急指針一般用途是使用戶可中止進(jìn)程。
11)選項、填充字段
可能包括“窗口擴(kuò)大因子”、“時間戳”等選項。長度可變,最長可達(dá) 40 字節(jié),當(dāng)沒有使用選項時,TCP 首部長度是 20 字節(jié)。
填充用于保證任選項為 32bit 的整數(shù)倍。
12)數(shù)據(jù)(長度可變)
TCP 首部結(jié)束之后的部分
UDP 報文格式
UDP 是 User Datagram Protocol 的簡稱, 中文名是用戶數(shù)據(jù)報協(xié)議,是一種無連接的傳輸層協(xié)議,提供面向事務(wù)的簡單不可靠信息傳送服務(wù)。
1)源端口(2 字節(jié)):發(fā)送方端口號
2)目的端口(2 字節(jié) ):接收方端口號
3)報文長度(2 字節(jié)):UDP 用戶數(shù)據(jù)報的總長度(頭部+數(shù)據(jù)),以字節(jié)為單位。
4)校驗和(2 字節(jié)):檢測 UDP 用戶數(shù)據(jù)報在傳輸中是否有錯,有錯就丟棄。
用于校驗 UDP 數(shù)據(jù)報的數(shù)字段和包含 UDP 數(shù)據(jù)報首部的“偽首部”。
偽首部,又稱為偽包頭(Pseudo Header):是指在 TCP 的分段或 UDP 的數(shù)據(jù)報格式中,在數(shù)據(jù)報首部前面增加源 IP 地址、目的 IP 地址、IP 分組的協(xié)議字段、TCP 或 UDP 數(shù)據(jù)報的總長度等共12字節(jié),所構(gòu)成的擴(kuò)展首部結(jié)構(gòu)。此偽首部是一個臨時的結(jié)構(gòu),它既不向上也不向下傳遞,僅僅只是為了保證可以校驗套接字的正確性。
5)數(shù)據(jù):UDP 的數(shù)據(jù)部分如果不為偶數(shù)需要用 0 填補(bǔ),就是說,如果數(shù)據(jù)長度為奇數(shù),數(shù)據(jù)長度加“1”
總結(jié)
以上是生活随笔為你收集整理的【Linux网络编程】TCP 和 UDP 数据报格式详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Linux网络编程】IP 数据报格式详
- 下一篇: 【Linux网络编程】原始套接字实例:发