??TCP協(xié)議是TCP/IP體系中非常復(fù)雜也是非常重要的協(xié)議,所以后面也會(huì)有更多的文章介紹該協(xié)議奕塑。
本文內(nèi)容
1 TCP特點(diǎn)
??(1) TCP 是面向連接的傳輸層協(xié)議柬赐。
應(yīng)用程序是使用TCP協(xié)議之前斑响,必須建立TCP連接凰慈。在傳送數(shù)據(jù)完畢后汞幢,必須釋放已建立的TCP連接。TCP連接是一條虛連接(邏輯連接)微谓,而不是一條真正的物理連接森篷。
??(2) 每一條TCP連接只能有兩個(gè)端點(diǎn)输钩,每條TCP連接只能是點(diǎn)對(duì)點(diǎn)的(一對(duì)一)。
??(3) TCP提供可靠交付的服務(wù)仲智。通過(guò)TCP連接傳送的數(shù)據(jù)买乃,無(wú)差錯(cuò)、不丟失钓辆、不重復(fù)剪验、并且按序達(dá)到。
??(4) TCP提供全雙工通信岩馍。
TCP允許通信雙方的應(yīng)用進(jìn)程在任何時(shí)候都能發(fā)送數(shù)據(jù)碉咆。TCP連接的兩端都設(shè)有發(fā)送緩存和接收緩存抖韩,用來(lái)臨時(shí)存放雙方通信的數(shù)據(jù)蛀恩。
??1) 發(fā)送緩存:用于存放準(zhǔn)備發(fā)送的數(shù)據(jù)和已發(fā)送但尚未收到確認(rèn)的數(shù)據(jù)(因?yàn)門CP提供可靠交付服務(wù),對(duì)于發(fā)送的數(shù)據(jù)必須要收到接收方的確認(rèn)回復(fù)茂浮,如果數(shù)據(jù)丟失了双谆,就可以從發(fā)送緩存中將剛發(fā)送的數(shù)據(jù)再發(fā)送一次,直到收到確認(rèn)回復(fù)后席揽,才會(huì)將這個(gè)數(shù)據(jù)從緩存中刪除)顽馋。
??2) 接收緩存:用于存放按序到達(dá)但尚未被接收應(yīng)用程序讀取的數(shù)據(jù)和不按序達(dá)到的數(shù)據(jù)。
??(5) TCP面向字節(jié)流幌羞。流是指流入進(jìn)程或從進(jìn)程流出的字節(jié)序列寸谜。
雖然應(yīng)用程序和TCP的交互是一次一個(gè)數(shù)據(jù)塊(大小可以不等),但是TCP把應(yīng)用程序交下來(lái)的數(shù)據(jù)塊看成僅僅一連串的無(wú)結(jié)構(gòu)的字節(jié)流属桦。
??如下圖所示熊痴,假如發(fā)送方要發(fā)送一個(gè)文件,會(huì)將這個(gè)文件按字節(jié)排序并編號(hào)聂宾,在發(fā)送時(shí)將這些字節(jié)放入TCP緩存中果善,從緩存中取出若干字節(jié)(可以不等)并加上TCP首部形成一個(gè)完整的報(bào)文段在鏈路上傳送,最終到達(dá)接收方的TCP緩存中系谐。
TCP并不關(guān)心應(yīng)用進(jìn)程依次把多長(zhǎng)的報(bào)文發(fā)送到TCP緩存中巾陕,而是根據(jù)接收方和當(dāng)前網(wǎng)絡(luò)擁塞的程度來(lái)決定一個(gè)報(bào)文段應(yīng)包含多少個(gè)字節(jié)。所以如果應(yīng)用進(jìn)程傳送到TCP緩存中的數(shù)據(jù)塊太長(zhǎng)纪他,TCP就可以把它劃分短一些再傳送鄙煤,而UDP是面向報(bào)文的,應(yīng)用進(jìn)程給出的數(shù)據(jù)塊UDP就是按照給出的長(zhǎng)度發(fā)送茶袒。
2 TCP的連接
??每條TCP連接有兩個(gè)端點(diǎn)馆类,TCP連接的端點(diǎn)叫做套接字(socket)或插口,這里的套接字定義為:端口號(hào)拼接到IP地址即構(gòu)成了套接字弹谁。
??套接字的表示方法是在點(diǎn)分十進(jìn)制的IP地址后面寫上端口號(hào)乾巧,中間用冒號(hào)或逗號(hào)隔開句喜。
套接字 socket = (IP地址 : 端口號(hào))
例如,若IP地址為192.3.4.5沟于,端口號(hào)是80咳胃,那么得到的套接字就是(192.3.4.5:80)
??每條TCP連接唯一地被通信的兩個(gè)端點(diǎn)(即兩個(gè)套接字確定)所確定。即:
TCP連接 = {socket1,socket2} = {(IP1 : prot1),(IP2 : prot2)}
3 TCP報(bào)文段的首部格式
??一個(gè)TCP報(bào)文段分為首部和數(shù)據(jù)部分兩部分旷太。
??TCP報(bào)文段首部的前20個(gè)字節(jié)是固定的展懈,后面有4n(n是整數(shù))字節(jié)是根據(jù)需要而增加的選項(xiàng)。因此TCP首部的最小字節(jié)是20字節(jié)供璧。
??(1) 源端口和目的端口:各占2自己存崖,分別寫入源端口號(hào)和目的端口號(hào),TCP的分用功能也是通過(guò)端口實(shí)現(xiàn)的睡毒。
??(2) 序號(hào):占4字節(jié)来惧,序號(hào)范圍是[ 0 , 232 - 1],共 232個(gè)序號(hào)演顾。TCP是面向字節(jié)流的供搀,在一個(gè)TCP連接中傳送的字節(jié)流中的每一個(gè)字節(jié)都是按順序編號(hào)。首部中的序號(hào)字段值則指的是本報(bào)文段所發(fā)送的數(shù)據(jù)的第一字節(jié)的序號(hào)钠至。
序號(hào)是可以重用的葛虐,當(dāng)序號(hào)增加到 232 - 1后,下一個(gè)序號(hào)就又回到了0棉钧,所以序號(hào)邏輯上可以表示為一個(gè)循環(huán)數(shù)組屿脐。
例如,若一個(gè)報(bào)文段的序號(hào)字段值是301宪卿,而攜帶的數(shù)據(jù)共有100字節(jié)的诵,這就表明:本報(bào)文段的數(shù)據(jù)第一個(gè)字節(jié)的序號(hào)是301,最后一個(gè)字節(jié)的序號(hào)是400愧捕。如果還有下一個(gè)報(bào)文段奢驯,則其序號(hào)字段的的值應(yīng)為401。
??(3) 確認(rèn)號(hào):占4字節(jié)次绘,是期望收到對(duì)方下一個(gè)報(bào)文段的第一個(gè)數(shù)據(jù)字節(jié)的序號(hào)瘪阁。
例如,B正確收到了A發(fā)送過(guò)來(lái)的一個(gè)報(bào)文段邮偎,其序號(hào)字段值是501管跺,而該報(bào)文段的數(shù)據(jù)長(zhǎng)度是200字節(jié)(序號(hào)501~700),這表明B正確收到了A發(fā)送的到序號(hào)700為止的數(shù)據(jù)禾进,因此B期望收到A的下一個(gè)數(shù)據(jù)序號(hào)是701豁跑,TCP是可靠傳輸,收到數(shù)據(jù)后需要給發(fā)送方回復(fù)確認(rèn)信息泻云,所以B在收到數(shù)據(jù)后給A發(fā)送的確認(rèn)收到的報(bào)文段中就把確認(rèn)號(hào)置為701艇拍。
若確認(rèn)號(hào) = N,則表明:到序號(hào)N - 1為止的所有數(shù)據(jù)都已正確收到狐蜕。
??(4) 數(shù)據(jù)偏移:占4位,單位:4B卸夕。它指出TCP報(bào)文段數(shù)據(jù)起始處距離TCP報(bào)文段的起始處有多遠(yuǎn)层释。這個(gè)字段實(shí)際上是指出TCP報(bào)文段的首部長(zhǎng)度。
如上圖所示快集,如果數(shù)據(jù)偏移字段的值為:1101(十進(jìn)制13)贡羔,所以數(shù)據(jù)偏移的值為13 × 4B = 42B,所以可知TCP報(bào)文段數(shù)據(jù)部分的起始處到TCP報(bào)文段的起始處(即TCP首部的)
數(shù)據(jù)偏移占4位个初,最大值為1111乖寒,即15,即數(shù)據(jù)偏移的值最大為60字節(jié)(TCP首部最大長(zhǎng)度為60字節(jié))院溺,又TCP首部有固定的20字節(jié)楣嘁,所以TCP可選字段的長(zhǎng)度不能超過(guò)40字節(jié)。
??(5) 保留:占6位覆获,保留今后使用马澈。
??接下來(lái)是6個(gè)控制位
??(6) 緊急URG(URGent):僅當(dāng)URG = 1瓢省,表明后面的緊急指針字段才有效弄息。它表明系統(tǒng)此報(bào)文段有緊急數(shù)據(jù),應(yīng)盡快傳送(相當(dāng)于高優(yōu)先級(jí)數(shù)據(jù))勤婚,而不要按照原來(lái)的排隊(duì)順序來(lái)傳送摹量。
??前面說(shuō)到,在發(fā)送報(bào)文段時(shí)馒胆,需要將字節(jié)先存放在TCP緩存中缨称,如果發(fā)送應(yīng)用需要發(fā)送一個(gè)緊急指令,如中斷指令(Control + C)祝迂,如果不使用緊急數(shù)據(jù)睦尽,那么這兩個(gè)字符就存在TCP緩存的末尾,直到前面的數(shù)據(jù)處理完才將這兩個(gè)字符交給接收方型雳。
??當(dāng)URG = 1時(shí)当凡,發(fā)送應(yīng)用進(jìn)程就告訴發(fā)送方的TCP有緊急數(shù)據(jù)要傳送,于是發(fā)送方TCP就把緊急數(shù)據(jù)插入到本報(bào)文段數(shù)據(jù)的最前面纠俭,而在緊急數(shù)據(jù)之后的數(shù)據(jù)仍是普通數(shù)據(jù)沿量。
??(7) 確認(rèn)ACK(ACKnowledgment):僅當(dāng)ACK = 1時(shí)確認(rèn)號(hào)字段才有效。TCP規(guī)定冤荆,在連接建立后所有傳送的報(bào)文段都必須把ACK置1朴则。
??(8) 推送PSH(PuSH):通常如果TCP緩存中字節(jié)很少,TCP會(huì)等待積累有足夠多的字節(jié)后再構(gòu)成報(bào)文段發(fā)送出去钓简,當(dāng)發(fā)送方將 PSH 置為 1時(shí)乌妒,并立即創(chuàng)建一個(gè)報(bào)文段發(fā)送出去汹想,接收方TCP收到PSH = 1的報(bào)文段,就盡快地交付接收應(yīng)用進(jìn)程撤蚊,而不再等到整個(gè)緩存都填滿在向上交付欧宜。
這個(gè)字段適合在交互式的通信,在一端應(yīng)用進(jìn)程鍵入一個(gè)命令立即能夠收到對(duì)方的響應(yīng)拴魄,但是這種推送操作很少使用冗茸。
??(9) 復(fù)位RST(ReSeT):當(dāng)RST = 1時(shí),表明TCP連接中出現(xiàn)了嚴(yán)重差錯(cuò)匹中,必須釋放連接夏漱,然后再重新建立傳輸連接。RST置為1還可以用來(lái)拒絕一個(gè)非法的報(bào)文段或拒絕打開一個(gè)連接顶捷。RST也可稱為重建位或重置位挂绰。
??(10) 同步SYN(SYNchronization):在連接建立時(shí)用來(lái)同步序號(hào)。當(dāng)SYN = 1而ACK = 0時(shí)服赎,表明這是一個(gè)連接請(qǐng)求報(bào)文段葵蒂。對(duì)方同意建立連接,則應(yīng)在響應(yīng)的報(bào)文段中使用SYN = 1和ACK = 1.因此重虑,SYN 置為1表示這是一個(gè)連接請(qǐng)求或連接接收?qǐng)?bào)文践付。
??(11) 終止FIN(FINis):用來(lái)釋放一個(gè)連接。當(dāng)FIN = 1時(shí)缺厉,表明此報(bào)文段的發(fā)送方的數(shù)據(jù)發(fā)送完畢永高,并要求釋放傳輸連接。
??(12) 窗口:占2字節(jié)提针,是指發(fā)送本報(bào)文段的一方的接收窗口命爬。窗口的值表示:從本報(bào)文段首部中的確認(rèn)號(hào)算起,接收方目前允許對(duì)方發(fā)送的數(shù)據(jù)量辐脖。即窗口值作為接收方讓發(fā)送方設(shè)置其發(fā)送窗口的依據(jù)饲宛。之所以要有這個(gè)限制,是因?yàn)榻邮辗降臄?shù)據(jù)緩存空間是有限的嗜价。
例如艇抠,A是發(fā)送方,B是接收方炭剪,B給A發(fā)送一個(gè)確認(rèn)接收數(shù)據(jù)的報(bào)文练链,其確認(rèn)號(hào)701(表示701之前的所有數(shù)據(jù)都已經(jīng)正確收到,期望A下一個(gè)報(bào)文段的第一個(gè)數(shù)據(jù)字節(jié)序號(hào)為701)奴拦,窗口字段的值是1000媒鼓,這就是告訴發(fā)送方A:從701號(hào)算起,我的接收緩存還可以接收1000個(gè)字節(jié)數(shù)據(jù),在你給我發(fā)送數(shù)據(jù)的時(shí)候绿鸣,你需要考慮一下我的接收能力疚沐。
窗口字段明確指出了現(xiàn)在允許對(duì)方發(fā)送的數(shù)據(jù)量。窗口值是經(jīng)常在動(dòng)態(tài)變化潮模。
??(13) 校驗(yàn)和:占2字節(jié)亮蛔。校驗(yàn)和字段校驗(yàn)的范圍包括首部和數(shù)據(jù)這兩個(gè)部分。和UDP用戶數(shù)據(jù)報(bào)一樣擎厢,在計(jì)算校驗(yàn)和時(shí)究流,需要在TCP報(bào)文段的前面加上12字節(jié)的偽首部。偽首部的格式和UDP偽首部的格式一樣动遭,只是需要將協(xié)議字段改為6芬探,TCP協(xié)議號(hào)是6。
??(14) 緊急指針:緊急指針只有在URG= 1時(shí)才有意義厘惦,它和URG字段配合使用偷仿,它指出了報(bào)文段中緊急數(shù)據(jù)的字節(jié)數(shù),因此宵蕉,緊急指針指出了緊急數(shù)據(jù)的末尾在報(bào)文段中的位置酝静。
即使窗口的值為0也可以發(fā)送緊急數(shù)據(jù)。
??(15) 選項(xiàng)和填充:長(zhǎng)度可變羡玛,最長(zhǎng)可達(dá)40字節(jié)别智。填充字段是為了使整個(gè)TCP首部的長(zhǎng)度是4字節(jié)的整數(shù)倍。
4 幾個(gè)選項(xiàng)字段
??(1) 最大報(bào)文段長(zhǎng)度MSS(Maximum Segment Size):是指每個(gè)TCP報(bào)文段中數(shù)據(jù)字段的最大長(zhǎng)度缝左,即TCP報(bào)文段長(zhǎng)度減去TCP首部長(zhǎng)度亿遂。它是為了考慮網(wǎng)絡(luò)利用率浓若。
??TCP報(bào)文段的數(shù)據(jù)部分渺杉,需要加上TCP首部至少20個(gè)字節(jié)(即沒(méi)有可變部分)和IP首部至少20字節(jié)才能組成一個(gè)IP數(shù)據(jù)報(bào)。若選擇較小的MSS長(zhǎng)度挪钓,例如是越,MSS是1,即TCP報(bào)文段數(shù)據(jù)部分長(zhǎng)度為1個(gè)字節(jié)碌上,那么IP層傳輸?shù)臄?shù)據(jù)報(bào)的開銷至少有40個(gè)字節(jié)倚评,這就導(dǎo)致網(wǎng)絡(luò)的利用率降低。
??反之馏予,如果MSS非常大天梧,那么在IP層傳輸時(shí)就需要分片,在終點(diǎn)時(shí)需要將收到的各個(gè)分片重新組裝成原來(lái)的TCP報(bào)文段霞丧,這樣也會(huì)使網(wǎng)絡(luò)開銷變大呢岗。
??因此,MSS應(yīng)盡可能大些,只要在IP層輸層傳輸時(shí)不需要分片就行后豫。默認(rèn)值是536字節(jié)長(zhǎng)悉尾,因此所有在互聯(lián)網(wǎng)上的主機(jī)都應(yīng)能接受的報(bào)文段長(zhǎng)度是536 + 20 = 556字節(jié)。
??(2) 窗口擴(kuò)大:占3字節(jié)挫酿,這個(gè)選項(xiàng)是為了擴(kuò)大窗口构眯。TCP首部的窗口字段長(zhǎng)度是16位,因此最大的窗口大小是64K字節(jié)早龟,窗口擴(kuò)大中有一個(gè)字節(jié)表示移位值S惫霸。新的窗口值等于TCP首部中的窗口位數(shù)從16增加到(16 + S)。移位值允許使用的最大值是14葱弟,相當(dāng)于窗口最大值增加到2(16+14) - 1它褪。
窗口擴(kuò)大選項(xiàng)在雙方初始建立TCP連接時(shí)進(jìn)行協(xié)商,如果某一端實(shí)現(xiàn)了窗口擴(kuò)大翘悉,當(dāng)它不需要擴(kuò)大其窗口時(shí)茫打,可發(fā)送S = 0的選項(xiàng),使窗口大小回到16妖混。
??(3) 時(shí)間戳:占10字節(jié)老赤,其中最主要的是時(shí)間戳值字段(4字節(jié))和時(shí)間戳回送回答字段(4字節(jié))。時(shí)間戳選項(xiàng)有以下兩個(gè)功能:
??1) 計(jì)算往返時(shí)間RTT制市。發(fā)送方在報(bào)文段時(shí)把當(dāng)前時(shí)鐘的時(shí)間值放入時(shí)間戳字段抬旺,接收方在確認(rèn)該報(bào)文段時(shí)把時(shí)間戳字段復(fù)制到時(shí)間戳回送回答字段。因此祥楣,發(fā)送方在接收到確認(rèn)報(bào)文后开财,就可以準(zhǔn)確的計(jì)算出RTT來(lái)。
??2) 用于處理TCP序號(hào)超過(guò)232的情況误褪,這又稱為防止序號(hào)繞回PAWS(Protect Against Wrapped Sequence numbers)责鳍,后面再介紹。