4-4:TCP协议之TCP头部格式详解
文章目錄
- 一:TCP頭部格式詳解
- (1)4位首部長(zhǎng)度
- (2)序列號(hào)和確認(rèn)應(yīng)答號(hào)
- A:可靠性問(wèn)題
- B:32位序號(hào)和確認(rèn)號(hào)
- (3)窗口大小
- (4)標(biāo)志位
- (5)緊急指針
- A:帶外數(shù)據(jù)(out_of _band)
- B:URG
- (6)校驗(yàn)和
- 二:Linux中的TCP實(shí)現(xiàn)
一:TCP頭部格式詳解
(1)4位首部長(zhǎng)度
標(biāo)準(zhǔn)TCP報(bào)頭寬度為4個(gè)字節(jié),總計(jì)4×5=20個(gè)字節(jié),所以在收到一個(gè)TCP報(bào)頭后首先會(huì)讀取20個(gè)字節(jié)(也就是報(bào)頭信息)
報(bào)頭中的選項(xiàng)是可有也可以沒(méi)有的,關(guān)鍵就取決于4位首部長(zhǎng)度。它表示該TCP頭部有多少個(gè)32位bit(也就是有多少個(gè)4字節(jié))。這4位是一個(gè)無(wú)符號(hào)數(shù),取值范圍為0000~1111,也即是0到15,當(dāng)為1111時(shí)表示該TCP報(bào)頭有15個(gè)4字節(jié)(60字節(jié)),而標(biāo)準(zhǔn)長(zhǎng)度是20字節(jié),所以選項(xiàng)最多是40字節(jié)
4位首部長(zhǎng)度不可能是全0,因?yàn)門(mén)CP報(bào)頭長(zhǎng)度至少是20字節(jié),也就是至少是20/4=5,對(duì)應(yīng)二進(jìn)制序列為0101
于是TCP分離有效載荷和報(bào)頭時(shí),拿到TCP報(bào)文后先直接讀取20字節(jié),然后拿出4位首部長(zhǎng)度進(jìn)行分析,如果就是5那么剩下的就是數(shù)據(jù),如果不是5,再讀取相應(yīng)字節(jié)數(shù)即可
**TCP和UDP不一樣,UDP中有包長(zhǎng)度來(lái)確定數(shù)據(jù)的長(zhǎng)度,在TCP中是不需要包長(zhǎng)度的,因?yàn)門(mén)CP并不需要按照數(shù)據(jù)塊交付,是面向字節(jié)流的,怎么讀,讀多少是應(yīng)用層協(xié)議需要做的事情,而它只負(fù)責(zé)將其讀入緩沖區(qū)中。**報(bào)文的完整性依靠校驗(yàn)和完成
(2)序列號(hào)和確認(rèn)應(yīng)答號(hào)
A:可靠性問(wèn)題
可靠性涉及很多層面,比如數(shù)據(jù)有序,準(zhǔn)確等等。但是這一切一切都要有一個(gè)前提,那么就是如何保證數(shù)據(jù)對(duì)方收到?
假設(shè)有兩個(gè)人A和B隔著很遠(yuǎn)的距離喊話。A首先向B喊:**B你聽(tīng)到了沒(méi)有?**如果此時(shí)A沒(méi)有聽(tīng)到B的回應(yīng),那么對(duì)于A來(lái)說(shuō)他一般會(huì)有兩種感覺(jué):我說(shuō)的話你沒(méi)有聽(tīng)見(jiàn)或者你說(shuō)的話我沒(méi)有聽(tīng)見(jiàn), 顯而易見(jiàn)對(duì)于A來(lái)說(shuō)他更傾向于第一種感覺(jué),所以A在沒(méi)有得到反饋時(shí)他一定會(huì)再次喊話
那什么時(shí)候A能確認(rèn)B已經(jīng)收到了自己的信息呢?當(dāng)然是B的收到信息反饋給了A,也就是說(shuō)這種反饋信息只是對(duì)A是有價(jià)值的,A通過(guò)B的反饋信息確認(rèn)了我的信息已經(jīng)傳達(dá)到了。
但是這里又產(chǎn)生了新的問(wèn)題,對(duì)于A來(lái)說(shuō)它得到了B的反饋確認(rèn)了自己的信息已經(jīng)遞達(dá),但是對(duì)于B呢,B在發(fā)出反饋信息時(shí),對(duì)于B他如何確認(rèn)自己的反饋信息也傳達(dá)到了A那里了呢?,顯然A也發(fā)送反饋信息給B,如果B收到了那么B也就確認(rèn)了。但是這里往返傳遞,總會(huì)有一條消息處于未決狀態(tài),總有一條消息無(wú)法得到收到反饋,最后一條消息無(wú)法保證可靠性
所以互聯(lián)網(wǎng)通信中是不可能有絕對(duì)的可靠性的,只能保證相對(duì)的可靠性,也就是這種相對(duì)可靠性指的是,只要收到了對(duì)方的應(yīng)答,就認(rèn)為之前的數(shù)據(jù)對(duì)方已經(jīng)收到
于是我們說(shuō):TCP基于的是確認(rèn)應(yīng)答機(jī)制
在TCP三次握手中,客戶端發(fā)送請(qǐng)求號(hào),服務(wù)端給客戶端的反饋就是圖中的ACK。
如果ACK在傳輸途中丟了,如果服務(wù)端長(zhǎng)時(shí)間沒(méi)有接受到客戶端回應(yīng)時(shí),就會(huì)觸發(fā)重傳機(jī)制,進(jìn)行重傳。
這里有一個(gè)很大的誤區(qū):我們不需要對(duì)ACK再ACK,因?yàn)橐坏┠銓?duì)ACK進(jìn)行ACK了,那么你就需要對(duì)ACK的ACK再進(jìn)行ACK,這是一個(gè)無(wú)休無(wú)止的過(guò)程。確認(rèn)應(yīng)答并不是對(duì)ACK保證可靠性,而是通過(guò)ACK保證上一次發(fā)的消息時(shí)可靠的
B:32位序號(hào)和確認(rèn)號(hào)
網(wǎng)絡(luò)傳輸畢竟是遠(yuǎn)距離傳輸,所以會(huì)受到各種因素的影響,在傳輸過(guò)程中極有可能出現(xiàn)丟包的現(xiàn)象發(fā)生。而如果包都能達(dá)到,有可能會(huì)涉及到的亂序的問(wèn)題,所以如果保證數(shù)據(jù)按序到達(dá)也是可靠性的一種體現(xiàn)
32位序號(hào)
假如有三段TCP報(bào)文,需要按照以下順序發(fā)送給服務(wù)端
- 你好
- 在嗎
- 去吃飯
如果TCP沒(méi)有保證的有序的機(jī)制,那么這三段報(bào)文到達(dá)服務(wù)端的順序可能會(huì)多種多樣,比如
- 去吃飯
- 你好
- 在嗎
TCP中的32位序號(hào)可以保證數(shù)據(jù)有序到達(dá)。如果數(shù)據(jù)由客戶端發(fā)送給服務(wù)端,那么32位序號(hào)就由客戶端填寫(xiě),它保證的就是客戶端的數(shù)據(jù)有序到達(dá)服務(wù)端(反之亦然)。客戶端在發(fā)送時(shí)會(huì)為發(fā)送的數(shù)據(jù)報(bào)文進(jìn)行編號(hào),比如
服務(wù)端收到之后即便是亂序的,它也可以根據(jù)編號(hào)進(jìn)行排序
32位確認(rèn)號(hào)
上面的三條數(shù)據(jù):1“你好”,2“在嗎”,3“去吃飯”在客戶端發(fā)送出去后,服務(wù)端接受會(huì)給三個(gè)ACK,分別為ACK1,ACK2,ACK3。那么這里存在一個(gè)問(wèn)題,客戶端如何確認(rèn)現(xiàn)在到來(lái)的ACK是對(duì)我發(fā)出的哪一條數(shù)據(jù)的確認(rèn)反饋呢?,如果其中有一個(gè)ACK丟了,那還不亂套了。
32位確認(rèn)序號(hào)可以保證得到的ACK是相應(yīng)報(bào)文的反饋。舉個(gè)例子,客戶端個(gè)發(fā)送的順序?yàn)?,2,3,如果客戶端此時(shí)收到的ACK中的確認(rèn)序號(hào)是2,那么對(duì)于客戶端來(lái)說(shuō),它就認(rèn)為它之前發(fā)送的1號(hào)已經(jīng)收到了,現(xiàn)在應(yīng)該從2開(kāi)始發(fā),如果受到的ACK確認(rèn)序號(hào)是9,那么表示2也收到了。
所以如果發(fā)送順序?yàn)?,2,3,那么ACK順序則應(yīng)該為2,3,4。但如果確認(rèn)序號(hào)中2,3丟了,只收到了4,對(duì)于客戶端來(lái)說(shuō)它就會(huì)認(rèn)為3之前的數(shù)據(jù)已經(jīng)全部收到。所以這就代表TCP可以少量丟包
32位序號(hào)和確認(rèn)序號(hào)為什么要同時(shí)存在
需要注意的是TCP是全雙工的。客戶端給服務(wù)端發(fā)送時(shí),服務(wù)端關(guān)心的就是序號(hào),客戶端關(guān)心的確認(rèn)序號(hào)。但同時(shí)服務(wù)端也會(huì)給客戶端發(fā)送數(shù)據(jù),所以同時(shí)客戶端也會(huì)關(guān)心序號(hào),而服務(wù)端也會(huì)關(guān)心確認(rèn)序號(hào)
(3)窗口大小
窗口大小是指發(fā)送方接受緩沖區(qū)中剩余空間的容量,用于流量控制。
- 如下,接受和發(fā)送緩沖區(qū)
因?yàn)榇翱诖笮〉哪康木褪且寣?duì)方明白我這個(gè)接收端現(xiàn)在的接受緩沖區(qū)容量的大小,讓發(fā)送端看實(shí)際情況發(fā)送。不要造成我都快滿了,對(duì)方還硬要發(fā)的局面(雖然有滿了之后有重傳機(jī)制,但是這種占用網(wǎng)絡(luò)資源的行為是一種設(shè)計(jì)問(wèn)題)
(4)標(biāo)志位
TCP功能非常強(qiáng)大,有建立連接的、有關(guān)閉連接的,還有一些正常數(shù)據(jù)報(bào)文等等。那么雙方是如何區(qū)分不同功能的TCP報(bào)文呢?正是通過(guò)其中的標(biāo)志位,如果某個(gè)標(biāo)志位被設(shè)置為1,表示該標(biāo)志位生效。
SYN
當(dāng)SYN為1時(shí),表示希望建立連接,并在其【序列號(hào)】的字段1進(jìn)行序列號(hào)初始值的設(shè)定
FIN
當(dāng)該位為1時(shí),表示今后不再會(huì)有數(shù)據(jù)發(fā)送,希望斷開(kāi)連接。當(dāng)通信結(jié)束希望斷開(kāi)連接時(shí),通信雙發(fā)的主機(jī)可以相互交換FIN位為1的TCP段
ACK
當(dāng)該位位1時(shí),【確認(rèn)應(yīng)答】字段變?yōu)橛行?#xff0c;TCP規(guī)定除了最初建立連接時(shí)的SYN包之外該位必須設(shè)置為1
PSH
當(dāng)該位設(shè)置為1時(shí),表示發(fā)送端催促接收端盡管向應(yīng)用層交付數(shù)據(jù),及時(shí)清空緩沖區(qū),以便后續(xù)數(shù)據(jù)到來(lái)
RST
當(dāng)該位設(shè)置為1時(shí),表示TCP連接中出現(xiàn)異常必須強(qiáng)制斷開(kāi)連接。
URG
當(dāng)該位設(shè)置為1時(shí),表示TCP報(bào)文中發(fā)送的數(shù)據(jù)含有緊急數(shù)據(jù)。也就是16位緊急指針只有當(dāng)URG為1時(shí)才有效
(5)緊急指針
A:帶外數(shù)據(jù)(out_of _band)
傳輸層協(xié)議使用帶外數(shù)據(jù)(out-of-band,OOB)來(lái)發(fā)送一些重要的數(shù)據(jù),如果通信一方有重要的數(shù)據(jù)需要通知對(duì)方時(shí),協(xié)議能夠?qū)⑦@些數(shù)據(jù)快速地發(fā)送到對(duì)方.為了發(fā)送這些數(shù)據(jù),協(xié)議一般不使用與普通數(shù)據(jù)相同的通道,而是使用另外的通道
如何理解呢?你可以想象一個(gè)場(chǎng)景:銀行處理業(yè)務(wù)時(shí)人們需要排隊(duì),這時(shí)進(jìn)來(lái)了一個(gè)強(qiáng)盜,他搖搖晃晃,大搖大擺排隊(duì)直接走到了銀行職員前面,為什么他這么放肆呢?因?yàn)樗掷镉幸话褬?#xff0c;最后他用搶抵著職員的腦袋逼迫她先為自己辦理業(yè)務(wù)。
此時(shí)這個(gè)強(qiáng)盜就可以看作一個(gè)帶外數(shù)據(jù),而職員也一定會(huì)優(yōu)先處理他,因?yàn)樗靼状藭r(shí)情況很緊急。
B:URG
linux系統(tǒng)的套接字機(jī)制支持低層協(xié)議發(fā)送和接受帶外數(shù)據(jù).但是TCP協(xié)議沒(méi)有真正意義上的帶外數(shù)據(jù).為了發(fā)送重要協(xié)議,TCP提供了一種稱為緊急模式(urgentmode)的機(jī)制.TCP協(xié)議在數(shù)據(jù)段中設(shè)置URG位,表示進(jìn)入緊急模式.接收方可以對(duì)緊急模式采取特殊的處理.很容易看出來(lái),這種方式數(shù)據(jù)不容易被阻塞,可以通過(guò)在我們的服務(wù)器端程序里面捕捉SIGURG信號(hào)來(lái)及時(shí)接受數(shù)據(jù)或者使用帶OOB標(biāo)志的recv函數(shù)來(lái)接受.
(6)校驗(yàn)和
校驗(yàn)和失敗,丟棄數(shù)據(jù)。觸發(fā)重傳
- 比如發(fā)送順序報(bào)文1,2,3,4,5,其中3號(hào)報(bào)文校驗(yàn)和失敗,那么確認(rèn)應(yīng)答就是3,表示從3繼續(xù)開(kāi)始發(fā)。
二:Linux中的TCP實(shí)現(xiàn)
Linux中TCP的報(bào)頭本質(zhì)就是一個(gè)結(jié)構(gòu)體
struct tcphdr {__be16 source;//源端口號(hào)__be16 dest;//目的端口號(hào)__be32 seq;//序號(hào)__be32 ack_seq;//確認(rèn)序號(hào) #if defined(__LITTLE_ENDIAN_BITFIELD)//標(biāo)志位采用位段實(shí)現(xiàn)__u16 res1:4,doff:4,fin:1,syn:1,rst:1,psh:1,ack:1,urg:1,ece:1,cwr:1; #elif defined(__BIG_ENDIAN_BITFIELD)__u16 doff:4,res1:4,cwr:1,ece:1,urg:1,ack:1,psh:1,rst:1,syn:1,fin:1; #else #error "Adjust your <asm/byteorder.h> defines" #endif __be16 window;//窗口大小__sum16 check;//校驗(yàn)和__be16 urg_ptr;//緊急指針 };總結(jié)
以上是生活随笔為你收集整理的4-4:TCP协议之TCP头部格式详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: (王道408考研数据结构)第五章树-第一
- 下一篇: 【小白的CFD之旅】02 江小白