更好閱讀體驗(yàn):《理解 TCP 和 UDP》— By Gitbook
TCP 是面向字節(jié)流的晨横,但傳送的數(shù)據(jù)單元卻是報(bào)文段。
什么是報(bào)文箫柳?
例如一個(gè) 100kb 的 HTML 文檔需要傳送到另外一臺(tái)計(jì)算機(jī)手形,并不會(huì)整個(gè)文檔直接傳送過(guò)去,可能會(huì)切割成幾個(gè)部分悯恍,比如四個(gè)分別為 25kb 的數(shù)據(jù)段库糠。
而每個(gè)數(shù)據(jù)段再加上一個(gè) TCP 首部,就組成了 TCP 報(bào)文涮毫。
一共四個(gè) TCP 報(bào)文曼玩,發(fā)送到另外一個(gè)端。
另外一端收到數(shù)據(jù)包窒百,然后再剔除 TCP 首部黍判,組裝起來(lái)。
等到四個(gè)數(shù)據(jù)包都收到了篙梢,就能還原出來(lái)一個(gè)完整的 HTML 文檔了顷帖。
在 OSI 的七層協(xié)議中,第二層(數(shù)據(jù)鏈路層)的數(shù)據(jù)叫「Frame」渤滞,第三層(網(wǎng)絡(luò)層)上的數(shù)據(jù)叫「Packet」贬墩,第四層(傳輸層)的數(shù)據(jù)叫「Segment」。
TCP 報(bào)文 (Segment)妄呕,包括首部和數(shù)據(jù)部分陶舞。
而 TCP 的全部功能都體現(xiàn)在它首部中各字段的作用,只有弄清 TCP 首部各字段的作用才能掌握 TCP 的工作原理绪励。
TCP 報(bào)文段首部的前20個(gè)字節(jié)是固定的肿孵,后面有 4N 字節(jié)是根據(jù)需要而增加的。
下圖是把 TCP 報(bào)文中的首部放大來(lái)看疏魏。
TCP 的首部包括以下內(nèi)容:
- 源端口 source port
- 目的端口 destination port
- 序號(hào) sequence number
- 確認(rèn)號(hào) acknowledgment number
- 數(shù)據(jù)偏移 offset
- 保留 reserved
- 標(biāo)志位 tcp flags
- 窗口大小 window size
- 檢驗(yàn)和 checksum
- 緊急指針 urgent pointer
- 選項(xiàng) tcp options
下面展開(kāi)來(lái)描述個(gè)字段的意義和作用停做。
TCP 首部各字段的意義和作用
源端口和目的端口 Port
各占 2 個(gè) 字節(jié),共 4 個(gè)字節(jié)大莫。
用來(lái)告知主機(jī)該報(bào)文段是來(lái)自哪里以及傳送給哪個(gè)應(yīng)用程序(應(yīng)用程序綁定了端口)的蛉腌。
進(jìn)行 TCP 通訊時(shí),客戶端通常使用系統(tǒng)自動(dòng)選擇的臨時(shí)端口號(hào),而服務(wù)器則使用知名服務(wù)端口號(hào)烙丛。
序號(hào) Sequence Number
占 4 個(gè)字節(jié)舅巷。
TCP 是面向字節(jié)流的,在一個(gè) TCP 連接中傳輸?shù)淖止?jié)流中的每個(gè)字節(jié)都按照順序編號(hào)河咽。
例如 100 kb 的 HTML 文檔數(shù)據(jù)钠右,一共 102400 (100 * 1024) 個(gè)字節(jié),那么每一個(gè)字節(jié)就都有了編號(hào)库北,整個(gè)文檔的編號(hào)的范圍是 0 ~ 102399爬舰。
序號(hào)字段值指的是本報(bào)文段所發(fā)送的數(shù)據(jù)的第一個(gè)字節(jié)的序號(hào)们陆。
那么 100 的 HTML 文檔分割成四個(gè)等分之后寒瓦,
第一個(gè) TCP 報(bào)文段包含的是第一個(gè) 25kb 的數(shù)據(jù),0 ~ 25599 字節(jié)坪仇, 該報(bào)文的序號(hào)的值就是:0
第二個(gè) TCP 報(bào)文段包含的是第二個(gè) 25kb 的數(shù)據(jù)杂腰,25600 ~ 51199 字節(jié),該報(bào)文的序號(hào)的值就是:25600
......
根據(jù) 8 位 = 1 字節(jié)椅文,那么 4 個(gè)字節(jié)可以表示的數(shù)值范圍:[0, 2^32]喂很,一共 2^32 (4294967296) 個(gè)序號(hào)。
序號(hào)增加到最大值的時(shí)候皆刺,下一個(gè)序號(hào)又回到了 0.
也就是說(shuō) TCP 協(xié)議可對(duì) 4GB 的數(shù)據(jù)進(jìn)行編號(hào)少辣,在一般情況下可保證當(dāng)序號(hào)重復(fù)使用時(shí),舊序號(hào)的數(shù)據(jù)早已經(jīng)通過(guò)網(wǎng)絡(luò)到達(dá)終點(diǎn)或者丟失了羡蛾。
確認(rèn)號(hào) Acknowledgemt Number
占 4 個(gè)字節(jié)漓帅。
表示期望收到對(duì)方下一個(gè)報(bào)文段的序號(hào)值。
TCP 的可靠性痴怨,是建立在「每一個(gè)數(shù)據(jù)報(bào)文都需要確認(rèn)收到」的基礎(chǔ)之上的忙干。
就是說(shuō),通訊的任何一方在收到對(duì)方的一個(gè)報(bào)文之后浪藻,都要發(fā)送一個(gè)相對(duì)應(yīng)的「確認(rèn)報(bào)文」捐迫,來(lái)表達(dá)確認(rèn)收到。
那么爱葵,確認(rèn)報(bào)文施戴,就會(huì)包含確認(rèn)號(hào)。
例如萌丈,通訊的一方收到了第一個(gè) 25kb 的報(bào)文暇韧,該報(bào)文的 序號(hào)值=0,那么就需要回復(fù)一個(gè)確認(rèn)報(bào)文浓瞪,其中的確認(rèn)號(hào) = 25600.
數(shù)據(jù)偏移 Offset
占 0.5 個(gè)字節(jié) (4 位)懈玻。
這個(gè)字段實(shí)際上是指出了 TCP 報(bào)文段的首部長(zhǎng)度 ,它指出了 TCP報(bào)文段的數(shù)據(jù)起始處 距離 TCP報(bào)文的起始處 有多遠(yuǎn)。(注意 數(shù)據(jù)起始處 和 報(bào)文起始處 的意思)
一個(gè)數(shù)據(jù)偏移量 = 4 byte涂乌,由于 4 位二進(jìn)制數(shù)能表示的最大十進(jìn)制數(shù)字是 15艺栈,因此數(shù)據(jù)偏移的最大值是 60 byte,這也側(cè)面限制了 TCP 首部的最大長(zhǎng)度湾盒。
保留 Reserved
占 0.75 個(gè)字節(jié) (6 位)湿右。
保留為今后使用,但目前應(yīng)置為 0罚勾。
標(biāo)志位 TCP Flags
標(biāo)志位毅人,一共有 6 個(gè),分別占 1 位尖殃,共 6 位 丈莺。
每一位的值只有 0 和 1,分別表達(dá)不同意思送丰。
緊急 URG (Urgent)
當(dāng) URG = 1 的時(shí)候缔俄,表示緊急指針(Urgent Pointer)有效。
它告訴系統(tǒng)此報(bào)文段中有緊急數(shù)據(jù)器躏,應(yīng)盡快傳送俐载,而不要按原來(lái)的排隊(duì)順序來(lái)傳送。
URG 要與首部中的 緊急指針 字段配合使用登失。
確認(rèn) ACK (Acknowlegemt)
當(dāng) ACK = 1 的時(shí)候遏佣,確認(rèn)號(hào)(Acknowledgemt Number)有效。
一般稱(chēng)攜帶 ACK 標(biāo)志的 TCP 報(bào)文段為「確認(rèn)報(bào)文段」揽浙。
TCP 規(guī)定状婶,在連接建立后所有傳送的報(bào)文段都必須把 ACK 設(shè)置為 1。
推送 PSH (Push)
當(dāng) PSH = 1 的時(shí)候捏萍,表示該報(bào)文段高優(yōu)先級(jí)太抓,接收方 TCP 應(yīng)該盡快推送給接收應(yīng)用程序,而不用等到整個(gè) TCP 緩存都填滿了后再交付令杈。
復(fù)位 RST (Reset)
當(dāng) RST = 1 的時(shí)候走敌,表示 TCP 連接中出現(xiàn)嚴(yán)重錯(cuò)誤,需要釋放并重新建立連接逗噩。
一般稱(chēng)攜帶 RST 標(biāo)志的 TCP 報(bào)文段為「復(fù)位報(bào)文段」掉丽。
同步 SYN (SYNchronization)
當(dāng) SYN = 1 的時(shí)候,表明這是一個(gè)請(qǐng)求連接報(bào)文段异雁。
一般稱(chēng)攜帶 SYN 標(biāo)志的 TCP 報(bào)文段為「同步報(bào)文段」捶障。
在 TCP 三次握手中的第一個(gè)報(bào)文就是同步報(bào)文段,在連接建立時(shí)用來(lái)同步序號(hào)纲刀。
對(duì)方若同意建立連接项炼,則應(yīng)在響應(yīng)的報(bào)文段中使 SYN = 1 和 ACK = 1。
終止 FIN (Finis)
當(dāng) FIN = 1 時(shí),表示此報(bào)文段的發(fā)送方的數(shù)據(jù)已經(jīng)發(fā)送完畢锭部,并要求釋放 TCP 連接暂论。
一般稱(chēng)攜帶 FIN 的報(bào)文段為「結(jié)束報(bào)文段」。
在 TCP 四次揮手釋放連接的時(shí)候拌禾,就會(huì)用到該標(biāo)志取胎。
窗口大小 Window Size
占 2 字節(jié)。
該字段明確指出了現(xiàn)在允許對(duì)方發(fā)送的數(shù)據(jù)量湃窍,它告訴對(duì)方本端的 TCP 接收緩沖區(qū)還能容納多少字節(jié)的數(shù)據(jù)闻蛀,這樣對(duì)方就可以控制發(fā)送數(shù)據(jù)的速度。
窗口大小的值是指您市,從本報(bào)文段首部中的確認(rèn)號(hào)算起觉痛,接收方目前允許對(duì)方發(fā)送的數(shù)據(jù)量。
例如墨坚,假如確認(rèn)號(hào)是 701 秧饮,窗口字段是 1000映挂。這就表明泽篮,從 701 號(hào)算起,發(fā)送此報(bào)文段的一方還有接收 1000 (字節(jié)序號(hào)是 701 ~ 1700) 個(gè)字節(jié)的數(shù)據(jù)的接收緩存空間柑船。
校驗(yàn)和 TCP Checksum
占 2 個(gè)字節(jié)帽撑。
由發(fā)送端填充,接收端對(duì) TCP 報(bào)文段執(zhí)行 CRC 算法鞍时,以檢驗(yàn) TCP 報(bào)文段在傳輸過(guò)程中是否損壞亏拉,如果損壞這丟棄。
檢驗(yàn)范圍包括首部和數(shù)據(jù)兩部分逆巍,這也是 TCP 可靠傳輸?shù)囊粋€(gè)重要保障及塘。
緊急指針 Urgent Pointer
占 2 個(gè)字節(jié)。
僅在 URG = 1 時(shí)才有意義锐极,它指出本報(bào)文段中的緊急數(shù)據(jù)的字節(jié)數(shù)笙僚。
當(dāng) URG = 1 時(shí),發(fā)送方 TCP 就把緊急數(shù)據(jù)插入到本報(bào)文段數(shù)據(jù)的最前面灵再,而在緊急數(shù)據(jù)后面的數(shù)據(jù)仍是普通數(shù)據(jù)肋层。
因此,緊急指針指出了緊急數(shù)據(jù)的末尾在報(bào)文段中的位置翎迁。
參考
《后臺(tái)開(kāi)發(fā) 核心技術(shù)與應(yīng)用實(shí)踐》
《計(jì)算機(jī)網(wǎng)絡(luò)》