最早的 TCP 協(xié)議文檔是 RFC793玻募。
TCP 提供一種面向連接的只损、可靠的字節(jié)流服務(wù)。
面向連接容易理解,那么什么是字節(jié)流服務(wù)呢跃惫?
答:兩個(gè)應(yīng)用程序通過 TCP 連接交換 8 bit 字節(jié)構(gòu)成的字節(jié)流叮叹。TCP 不在字節(jié)流中插入記錄標(biāo)識(shí)符。我們將這成為字節(jié)流服務(wù)(byte stream service)爆存。另外蛉顽,TCP 對字節(jié)流的內(nèi)容不作任何解釋。TCP 不知道傳輸?shù)臄?shù)據(jù)字節(jié)流是二進(jìn)制數(shù)據(jù)先较,還是 ASCII 字符携冤、EDCDIC 字符或者其他類型數(shù)據(jù)。對字節(jié)流的解釋由 TCP 連接雙方的應(yīng)用層解釋闲勺。這種對字節(jié)流的處理方式與 Unix 操作系統(tǒng)對文件的處理方式很相似曾棕。Unix 內(nèi)核對一個(gè)應(yīng)用讀或?qū)懙膬?nèi)容不作任何解釋,而是交給應(yīng)用程序處理霉翔。對 Unix 的內(nèi)核來說睁蕾,它無法區(qū)分一個(gè)二進(jìn)制文件與一個(gè)文本文件。
TCP 通過下列方式來提供可靠性:
應(yīng)用數(shù)據(jù)被分割成 TCP 認(rèn)為最適合發(fā)送的數(shù)據(jù)塊(UDP 協(xié)議中债朵,應(yīng)用程序產(chǎn)生的數(shù)據(jù)報(bào)長度將保持不變)子眶。由 TCP 傳遞給 IP 的信息單位稱為報(bào)文段或段(segment)。
當(dāng) TCP 發(fā)出一個(gè)段后序芦,它啟動(dòng)一個(gè)定時(shí)器臭杰,等待目的端確認(rèn)收到這個(gè)報(bào)文段。如果不能及時(shí)收到一個(gè)確認(rèn)谚中,將重發(fā)這個(gè)報(bào)文段渴杆。這也就是所謂的超時(shí)及重傳策略。
當(dāng) TCP 收到發(fā)自 TCP 連接另一端的數(shù)據(jù)時(shí)宪塔,它將發(fā)送一個(gè)確認(rèn)磁奖。這個(gè)確認(rèn)不是立即發(fā)送,通常將推遲幾分之一秒某筐。
TCP 將保持它首部和數(shù)據(jù)的校驗(yàn)和比搭。這是一個(gè)端到端的校驗(yàn)和,目的是檢測數(shù)據(jù)在傳輸過程中的任何變化南誊。如果收到段的校驗(yàn)和有差錯(cuò)身诺,TCP 將丟棄這個(gè)報(bào)文段和不確認(rèn)收到此報(bào)文段,以便發(fā)端收取確認(rèn)響應(yīng)時(shí)超時(shí)并重發(fā)抄囚。
因?yàn)?IP 數(shù)據(jù)報(bào)的到達(dá)可能會(huì)失序霉赡,因此 TCP 報(bào)文段的到達(dá)也可能會(huì)失序。如有必要幔托,TCP 將對收到的數(shù)據(jù)進(jìn)行重新排序穴亏,以正確的順序交給應(yīng)用層。
IP 數(shù)據(jù)報(bào)也可能會(huì)發(fā)送重復(fù),所以 TCP 的接收端必須丟棄重復(fù)的數(shù)據(jù)嗓化。
TCP 還能提供流量控制锅劝。TCP 連接的每一方都有固定大小的緩沖空間。TCP 的接收端只允許另一端發(fā)送接收端緩沖區(qū)所能容納的數(shù)據(jù)蟆湖。這將防止較快主機(jī)致使較慢主機(jī)的緩沖區(qū)溢出故爵。
TCP 首部
如果不計(jì)任選字段,TCP 首部通常是 20 個(gè)字節(jié)隅津。
序號用來標(biāo)識(shí)從 TCP 發(fā)端向 TCP 收端發(fā)送的數(shù)據(jù)字節(jié)流诬垂,它表示在這個(gè)報(bào)文段中的第一個(gè)數(shù)據(jù)字節(jié)。如果將字節(jié)流看作在兩個(gè)應(yīng)用程序間的單向流動(dòng)伦仍,則 TCP 用序號對每個(gè)字節(jié)進(jìn)行計(jì)數(shù)结窘。序號是 32 bit 的無符號數(shù),序號到達(dá) 2^32 -1 后又從 0 開始充蓝。
當(dāng)建立一個(gè)新連接時(shí)隧枫,SYN 標(biāo)志變 1。序號字段包含由這個(gè)主機(jī)選擇的該連接的初始序號 ISN(Initial Sequence Number)谓苟。該主機(jī)要發(fā)送數(shù)據(jù)的第一個(gè)字節(jié)序號為這個(gè) ISN 加 1官脓,因?yàn)?SYN 標(biāo)志消耗了一個(gè)序號(FIN 標(biāo)志也要占用一個(gè)序號)。
既然每個(gè)傳輸?shù)淖止?jié)都被計(jì)數(shù)涝焙,確認(rèn)序號包含發(fā)送確認(rèn)的一端所期望收到的下一個(gè)序號卑笨。只有 ACK 標(biāo)志為 1 時(shí)確認(rèn)序號字段才有效。發(fā)送 ACK 無需任何代價(jià)仑撞,因?yàn)?32 bit 的確認(rèn)序號字段和 ACK 標(biāo)志一樣赤兴,總是 TCP 首部的一部分。因此隧哮,我們看到一旦一個(gè)連接建立起來桶良,這個(gè)字段總是被設(shè)置,ACK 標(biāo)志也總是被設(shè)置為 1沮翔。TCP 為應(yīng)用層提供全雙工服務(wù)陨帆。這意味著數(shù)據(jù)能在兩個(gè)方向上獨(dú)立地進(jìn)行傳輸。因此鉴竭,連接的每一端必須保持每個(gè)方向上的傳輸數(shù)據(jù)序號歧譬。
TCP 可以表述為一個(gè)沒有選擇確認(rèn)或否認(rèn)的滑動(dòng)窗口協(xié)議(滑動(dòng)窗口協(xié)議用于數(shù)據(jù)傳輸)岸浑。我們說 TCP 缺少選擇確認(rèn)是因?yàn)?TCP 首部中的確認(rèn)序號表示發(fā)方已成功收到字節(jié)搏存,但還不包含確認(rèn)序號所指的字節(jié)。當(dāng)前還無法對數(shù)據(jù)流中選定的部分進(jìn)行確認(rèn)矢洲。例如璧眠,如果 1 ~ 1024 字節(jié)已經(jīng)成功收到,下一報(bào)文段中包含序號從 2049 ~ 3072 的字節(jié),收端并不能確認(rèn)這個(gè)新的報(bào)文段责静。它所能做的就是發(fā)回一個(gè)確認(rèn)序號為 1025 的 ACK袁滥。它也無法對一個(gè)報(bào)文段進(jìn)行否認(rèn)。例如灾螃,如果收到包含 1025 ~ 2048 字節(jié)的報(bào)文段题翻,但它的校驗(yàn)和錯(cuò),TCP 接收端所能做的就是發(fā)回一個(gè)確認(rèn)序號為 1025 的 ACK腰鬼。而重復(fù)的確認(rèn)可以幫助發(fā)端確定分組已經(jīng)丟失嵌赠。
首部長度給出首部中 32 bit 字的數(shù)據(jù)。需要這個(gè)值是因?yàn)槿芜x字段的長度是可變的熄赡。這個(gè)字段占 4 bit姜挺,因此 TCP 最多有 60 字節(jié)的首部。然而彼硫,沒有任選字段炊豪,正常的長度是 20 字節(jié)。
其他首部字段
| 字段名 | 字段作用 |
| URG | 緊急指針(urgent pointer)有效 |
| ACK | 確認(rèn)序號有效 |
| PSH | 接收方應(yīng)該盡快將這個(gè)報(bào)文段交給應(yīng)用層 |
| RST | 重建連接 |
| SYN | 同步序號用來發(fā)起一個(gè)連接 |
| FIN | 發(fā)端完成發(fā)送任務(wù) |
TCP 的流量控制由連接的每一端通過聲明的窗口大小來提供拧篮。窗口大小為字節(jié)數(shù)词渤,起始于確認(rèn)序號字段指明的值,這個(gè)值是接收端正期望接收的字節(jié)串绩。窗口大小是一個(gè) 16 bit 字段掖肋,因而窗口大小最大為 65535 字節(jié)。后面還有新的窗口刻度選項(xiàng)赏参,它允許這個(gè)值按比例變化以提供更大的窗口志笼。
校驗(yàn)和覆蓋了整個(gè) TCP 報(bào)文段:TCP 首部和 TCP 數(shù)據(jù)。這是一個(gè)強(qiáng)制性的字段把篓,一定是由發(fā)端計(jì)算和存儲(chǔ)纫溃,并由收端進(jìn)行驗(yàn)證。TCP 校驗(yàn)和的計(jì)算和 UDP 校驗(yàn)和的計(jì)算相似韧掩。
只有 URG 標(biāo)志置為 1 時(shí)緊急指針才有效紊浩。緊急指針是一個(gè)正的偏移量,和序號字段中的值相加表示緊急數(shù)據(jù)最后一個(gè)字節(jié)的序號疗锐。TCP 的緊急方式是發(fā)送端向另一端發(fā)送緊急數(shù)據(jù)的一種方式坊谁。
最常見的可選字段是最長報(bào)文大小,又稱為 MSS(Maximum Segment Size)滑臊。每個(gè)連接方通常都在通信的第一個(gè)報(bào)文段(為建立連接而設(shè)置 SYN 標(biāo)志的那個(gè)段)中指明這個(gè)選項(xiàng)口芍。它指明本端所能接收的最大長度的報(bào)文段。
從上圖中可以看出:TCP 報(bào)文段的數(shù)據(jù)部分是可選的雇卷。所以我們可以從建立連接到連接終止都使用沒有數(shù)據(jù)的報(bào)文段鬓椭。