TCP协议的一些认识及实践
生活随笔
收集整理的這篇文章主要介紹了
TCP协议的一些认识及实践
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
http://www.2cto.com/net/201210/163047.html 一、簡介 引用《TCP/IP詳解-卷1》中的介紹,TCP與UDP使用相同的網(wǎng)絡(luò)層(IP層),TCP卻向應(yīng)用層提供了與UDP完全不同的服務(wù)。TCP提供一種面向連接的、可靠的字節(jié)流服務(wù)。 所謂面向連接的,是指在彼此通信前要先建立連接。同時(shí)這種點(diǎn)對點(diǎn)的連接表明了TCP不支持多播和廣播。 所謂可靠的,是指TCP有一堆保證數(shù)據(jù)傳輸準(zhǔn)確的機(jī)制。 ? www.2cto.com ?
? 所謂字節(jié)流,是指TCP接收端并不知道發(fā)送端每次向該連接寫入了多少數(shù)據(jù),只關(guān)心通過限制能從連接中最大字節(jié)數(shù)。 二、協(xié)議格式 圖:TCP數(shù)據(jù)包結(jié)構(gòu) 圖:TCP包首部結(jié)構(gòu) 字段說明: 16位源端口號:指建立連接(或發(fā)送數(shù)據(jù))的端口號 16位目的端口號:指連接另一端(或接受數(shù)據(jù))的端口號 32位序號:發(fā)送的字節(jié)序號,如果是新建立的連接,則第一個(gè)包的seq為0,否則為上一個(gè)數(shù)據(jù)包的確認(rèn)序號。同一個(gè)包中的序號和確認(rèn)序號是不同的。 ? www.2cto.com ?
? 32位確認(rèn)序號:等于接收到數(shù)據(jù)包的序號seq+數(shù)據(jù)包的長度len。同時(shí)告訴對端,下一個(gè)數(shù)據(jù)包的開頭字節(jié)序號。 4位首部長度:tcp包首部的長度。 URG:緊急指針有效。它使一端可以告訴另一端有些具有某種方式的“緊急數(shù)據(jù)”已經(jīng)放置在普通的數(shù)據(jù)流中。另一端被通知這個(gè)緊急數(shù)據(jù)已被放置在普通數(shù)據(jù)流
? 中,由接收方?jīng)Q定如何處理。URG比特被置1,并且一個(gè)16bit的緊急指針被置為一個(gè)正的偏移量,該偏移量必須與TCP首部中的序號字段相加,以便得出緊急數(shù)據(jù)的最后一個(gè)字節(jié)的序號。注意:TCP的緊急方式不是帶外數(shù)據(jù)(out-of-band data)。緊急方式有什么作用呢?兩個(gè)最常見的例子是Telnet和Rlogin。當(dāng)交互用戶鍵入中斷鍵時(shí),另一個(gè)例子是FTP,當(dāng)交互用戶放棄一個(gè)文件的傳輸時(shí)。如果在接收方處理第一個(gè)緊急指針之前,發(fā)送方多次進(jìn)入緊急方式會發(fā)生什么情況呢?在數(shù)據(jù)流中的緊急指針會向前移動(dòng),而其在接收方的前一個(gè)位置將丟失。接收方只有一個(gè)緊急指針,每當(dāng)對方有新的值到達(dá)時(shí)它將被覆蓋。這意味著如果發(fā)送方進(jìn)入緊急方式時(shí)所寫的內(nèi)容對接收方非常重要,那么這些字節(jié)數(shù)據(jù)必須被發(fā)送方用某種方式特別標(biāo)記。我們將看到Telnet通過在數(shù)據(jù)流中加入一個(gè)值為255的字節(jié)作為前綴來標(biāo)記它所有的命令。 ? www.2cto.com ?
? ACK:確認(rèn)序號有效 PSH:接收方應(yīng)盡快將這個(gè)報(bào)文段交給應(yīng)用層。發(fā)送方使用PUSH標(biāo)志通知接收方將所收到的數(shù)據(jù)全部提交給接收進(jìn)程。這里的數(shù)據(jù)包括與PUSH一起傳送的數(shù)據(jù)以及接收方TCP已經(jīng)為接收進(jìn)程收到的其他數(shù)據(jù)(還在TCP的緩沖區(qū)中)。
? RST:重置連接 SYN:同步信號,用于發(fā)起一個(gè)連接 FIN:發(fā)端完成發(fā)送任務(wù),關(guān)閉連接 16位窗口大小:TCP的流量控制由連接的每一端通過聲明的窗口大小來提供。窗口大小為字節(jié)數(shù),起始于確認(rèn)序號字段指明的值,這個(gè)值是接收端正期望接收的字節(jié)。窗口大小是一個(gè)16 bit字段,因而窗口大小最大為65535字節(jié)。 ? www.2cto.com ?
? 16位校驗(yàn)和:檢驗(yàn)和覆蓋了整個(gè)的TCP報(bào)文段:TCP首部和TCP數(shù)據(jù)。 16位緊急指針:只有當(dāng)URG標(biāo)志置1時(shí)緊急指針才有效。緊急指針是一個(gè)正的偏移量,和序號字段中的值相加表示緊急數(shù)據(jù)最后一個(gè)字節(jié)的序號。TCP的緊急方式是發(fā)送端向另一端發(fā)送緊急數(shù)據(jù)的一種方式。 選項(xiàng):部分可選配置,主要有以下幾種: 每個(gè)選項(xiàng)的開始是1字節(jié)kind字段,說明選項(xiàng)的類型。kind字段為0和1的選項(xiàng)僅占1個(gè)字節(jié)。其他的選項(xiàng)在kind字節(jié)后還有l(wèi)en字節(jié)。它說明的長度是指總長度,包括kind字節(jié)和len字節(jié)。 ? www.2cto.com ? 三、TCP各種狀態(tài) 1. 狀態(tài)轉(zhuǎn)移 A?主動(dòng)建立連接 圖:主動(dòng)建立連接 B?被動(dòng)建立連接 圖:被動(dòng)建立連接 C?主動(dòng)關(guān)閉連接 圖:主動(dòng)關(guān)閉連接 D?被動(dòng)關(guān)閉連接 圖:被動(dòng)關(guān)閉連接 2. 建立連接 圖:TCP建立連接 3. 關(guān)閉連接 圖:TCP關(guān)閉連接 4. 半連接 TCP連接是個(gè)全雙工通道,所以可以同時(shí)支持發(fā)送和接收。可以認(rèn)為將一個(gè)通道分成兩部分,就像高速公路一樣,一條大路中間分隔,兩邊的方向完全相反。 半連接是指連接的一端發(fā)送完本地?cái)?shù)據(jù)后,將發(fā)送的那半個(gè)連接關(guān)閉,告訴對端不用再等待接收數(shù)據(jù),而對端照樣可以發(fā)送數(shù)據(jù),本端可以讀取數(shù)據(jù)。 再舉高速公路的例子,假如連接是北京到天津的高速公路,如果某一天,北京到天津方向的沒有車輛,則該方向高速公路可以封閉,北京這邊的入口將關(guān)閉,同時(shí)告知天津出口不會有車輛通行,天津出口也沒必要有人值班了。但是,有不少車輛要從天津開往北京方向,這樣天津的入口沒有關(guān)閉,北京的出口則需要有人收費(fèi)抬桿。
? 5. 復(fù)位報(bào)文 無論何時(shí)一個(gè)報(bào)文段發(fā)往基準(zhǔn)的連接(referenced connection)出現(xiàn)錯(cuò)誤,TCP都會發(fā)出一個(gè)復(fù)位報(bào)文段(這里提到的“基準(zhǔn)的連接”是指由目的I P地址和目的端口號以及源I P地址和源端口號指明的連接。) 產(chǎn)生復(fù)位的一種常見情況是當(dāng)連接請求到達(dá)時(shí),目的端口沒有進(jìn)程正在聽。對于UDP,當(dāng)一個(gè)數(shù)據(jù)報(bào)到達(dá)目的端口時(shí),該端口沒在使用,它將產(chǎn)生一個(gè)ICMP端口不可達(dá)的信息。而TCP則使用復(fù)位。
? 發(fā)送一個(gè)復(fù)位報(bào)文段而不是FIN來中途釋放一個(gè)連接,這稱為異常釋放。異常終止一個(gè)連接對應(yīng)用程序來說有兩個(gè)優(yōu)點(diǎn):(1)丟棄任何待發(fā)數(shù)據(jù)并立即發(fā)送復(fù)位報(bào)文段;(2)RST的接收方會區(qū)分另一端執(zhí)行的是異常關(guān)閉還是正常關(guān)閉。應(yīng)用程序使用的API必須提供產(chǎn)生異常關(guān)閉而不是正常關(guān)閉的手段。Socket API通過“l(fā)inger on close”選項(xiàng)(SO_LINGER)提供了這種異常關(guān)閉的能力。我們加上-L選項(xiàng)并將停留時(shí)間設(shè)為0。這將導(dǎo)致連接關(guān)閉時(shí)進(jìn)行復(fù)位而不是正常的FIN。 四、TCP數(shù)據(jù)傳輸 1. 正常傳輸 圖:正常的數(shù)據(jù)傳輸 2. 快發(fā)慢接 圖:快發(fā)到慢收的數(shù)據(jù)傳輸 上圖說明,在慢收設(shè)備接收數(shù)據(jù)時(shí),由于沒有及時(shí)的將TCP緩沖區(qū)的數(shù)據(jù)讀到應(yīng)用層而會返回給發(fā)送端一個(gè)通告窗口為0的ACK。 五、超時(shí)和重傳機(jī)制 1. 往返時(shí)間RTT及重傳超時(shí)間RTO(Retransmission TimeOut) RTT估計(jì)器:R←aR+ ( 1-a )M 這里的a是一個(gè)推薦值為0.9的平滑因子。每次進(jìn)行新測量的時(shí)候,這個(gè)被平滑的RTT將得到更新。每個(gè)新估計(jì)的90%來自前一個(gè)估計(jì),而10 %則取自新的測量。 RTO公式: E rr= M-A A←A+ g E rr D←D+ h( | E rr |-D) RTO= A+ 4D 這里的A是被平滑的RTT(均值的估計(jì)器)而D則是被平滑的均值偏差。Err是剛得到的測量結(jié)果與當(dāng)前的RTT估計(jì)器之差。A和D均被用于計(jì)算下一個(gè)重傳時(shí)間(RTO)。增量g起平均作用,取為1/8(0.125)。偏差的增益是h,取值為0.25。當(dāng)RTT變化時(shí),較大的偏差增益將使RTO快速上升。 一個(gè)TCP連接只有一個(gè)RTT計(jì)時(shí)器,如果一個(gè)請求發(fā)送時(shí)計(jì)時(shí)器已經(jīng)開始計(jì)時(shí),則該請求不進(jìn)行RTT計(jì)算。 圖:RTT計(jì)時(shí) 上圖中,第4個(gè)數(shù)據(jù)包在發(fā)送時(shí)因?yàn)镽TT計(jì)時(shí)器已經(jīng)開始計(jì)時(shí)(第3個(gè)數(shù)據(jù)包)而沒有再次啟動(dòng)計(jì)時(shí)器。 2.? 擁塞避免算法 有兩種分組丟失的指示:發(fā)生超時(shí)和接收到重復(fù)的確認(rèn)。 擁塞避免算法和慢啟動(dòng)算法是兩個(gè)目的不同、獨(dú)立的算法。但是當(dāng)擁塞發(fā)生時(shí),我們希望降低分組進(jìn)入網(wǎng)絡(luò)的傳輸速率,于是可以調(diào)用慢啟動(dòng)來作到這一點(diǎn)。 擁塞避免算法和慢啟動(dòng)算法需要對每個(gè)連接維持兩個(gè)變量:一個(gè)擁塞窗口cwnd和一個(gè)慢啟動(dòng)門限ssthresh。算法如下: 1)? 對一個(gè)給定的連接,初始化cwnd為1個(gè)報(bào)文段,ssthresh為65535個(gè)字節(jié)。 2)? TCP輸出例程的輸出不能超過cwnd和接收方通告窗口的大小。擁塞避免是發(fā)送方使用的流量控制,而通告窗口則是接收方進(jìn)行的流量控制。前者是發(fā)送方感受到的網(wǎng)絡(luò)擁塞的估計(jì),而后者則與接收方在該連接上的可用緩存大小有關(guān)。 3)? 當(dāng)擁塞發(fā)生時(shí)(超時(shí)或收到重復(fù)確認(rèn)),ssthresh被設(shè)置為當(dāng)前窗口大小的一半(cwnd和接收方通告窗口大小的最小值,但最少為2個(gè)報(bào)文段)。此外,如果是超時(shí)引起了擁塞,則cwnd被設(shè)置為1個(gè)報(bào)文段(這就是慢啟動(dòng))。
? 4)? 當(dāng)新的數(shù)據(jù)被對方確認(rèn)時(shí),就增加cwnd,但增加的方法依賴于我們是否正在進(jìn)行慢啟動(dòng)或擁塞避免。如果cwnd小于或等于ssthresh,則正在進(jìn)行慢啟動(dòng),否則正在進(jìn)行擁塞避免。慢啟動(dòng)一直持續(xù)到我們回到當(dāng)擁塞發(fā)生時(shí)所處位置的半時(shí)候才停止(因?yàn)槲覀冇涗浟嗽诓襟E2中給我們制造麻煩的窗口大小的一半),然后轉(zhuǎn)為執(zhí)行擁塞避免。 慢啟動(dòng)算法初始設(shè)置cwnd為1個(gè)報(bào)文段,此后每收到一個(gè)確認(rèn)就加1。 擁塞避免算法要求每次收到一個(gè)確認(rèn)時(shí)將cwnd增加1/cwnd。與慢啟動(dòng)的指數(shù)增加比起來,這是一種加性增長(additive increase)。我們希望在一個(gè)往返時(shí)間內(nèi)最多為cwnd增加1個(gè)報(bào)文段(不管在這個(gè)RTT中收到了多少個(gè)ACK),然而慢啟動(dòng)將根據(jù)這個(gè)往返時(shí)間中所收到的確認(rèn)的個(gè)數(shù)增加cwnd。 圖:慢啟動(dòng)和擁塞避免的可視化描述 3.? 快速重傳與快速恢復(fù)算法 在收到一個(gè)失序的報(bào)文之后,TCP需要立即產(chǎn)生一個(gè)ACK(一個(gè)重復(fù)的ACK)。這個(gè)ACK不應(yīng)該被延遲。該重復(fù)的ACK是為了讓對方知道收到一個(gè)失序的報(bào)文段,并告訴對方自己希望收到的報(bào)文序號。 問題出現(xiàn)了,有兩種可能我們會收到重復(fù)的ACK:丟包和報(bào)文段失序。如果是報(bào)文段失序了,那么在發(fā)送一兩個(gè)重復(fù)的ACK之后,基本上都能接收到失序的幾個(gè)報(bào)文,然后在TCP緩沖區(qū)中重新排序,然后返回另一個(gè)ACK(希望收到的下一個(gè)報(bào)文的序號);而如果有三個(gè)或三個(gè)以上的重復(fù)ACK,那么認(rèn)為該ACK對應(yīng)的數(shù)據(jù)已經(jīng)丟失,需要立即進(jìn)行重傳,無需等待超時(shí)定時(shí)器溢出。這就是快速重傳算法。 圖:TCP超時(shí)重傳 上圖可以看出,發(fā)送端在連續(xù)收到了3個(gè)重復(fù)的ACK報(bào)文后,并沒有進(jìn)入慢啟動(dòng),而是執(zhí)行了擁塞避免算法,這就是快速回復(fù)算法。之所以沒有執(zhí)行慢啟動(dòng)算法是因?yàn)?#xff0c;發(fā)送端收到了連續(xù)的重復(fù)的ACK報(bào)文段后,不僅判斷出這個(gè)報(bào)文已經(jīng)丟失,還能判斷到接收端收到了后面的幾個(gè)報(bào)文段(只有這樣,接收端才連續(xù)的返回重復(fù)ACK報(bào)文),表明這時(shí)候的網(wǎng)絡(luò)仍然可以傳輸報(bào)文,沒有必要執(zhí)行慢啟動(dòng)影響傳輸性能,所以,在接收到重傳報(bào)文段的ACK之前,又發(fā)出了三個(gè)報(bào)文段67、69和71。
? 這個(gè)算法通常按如下過程進(jìn)行實(shí)現(xiàn): 1) 當(dāng)收到第3個(gè)重復(fù)的ACK時(shí),將ssthresh設(shè)置為當(dāng)前擁塞窗口cwnd的一半。重傳丟失的報(bào)文段。設(shè)置cwnd為ssthresh加上3倍的報(bào)文段大小。 2) 每次收到另一個(gè)重復(fù)的ACK時(shí),cwnd增加1個(gè)報(bào)文段大小并發(fā)送1個(gè)分組(如果新的cwnd允許發(fā)送)。 3) 當(dāng)下一個(gè)確認(rèn)新數(shù)據(jù)的A C K到達(dá)時(shí),設(shè)置cwnd為ssthresh(在第1步中設(shè)置的值)。這個(gè)ACK應(yīng)該是在進(jìn)行重傳后的一個(gè)往返時(shí)間內(nèi)對步驟1中重傳的確認(rèn)。另外,這個(gè)ACK也應(yīng)該是對丟失的分組和收到的第1個(gè)重復(fù)的ACK之間的所有中間報(bào)文段的確認(rèn)。這一步采用的是擁塞避免,因?yàn)楫?dāng)分組丟失時(shí)我們將當(dāng)前的速率減半。 4.? 擁塞算法例子 1)? 初始SYN有一個(gè)超時(shí)重傳的例子 ?圖:SYN超時(shí)重傳-擁塞避免例子 當(dāng)SYN的超時(shí)發(fā)生時(shí),sstresh被置為其最小取值(512字節(jié),表示2個(gè)報(bào)文段)。為進(jìn)入慢啟動(dòng)階段,cwnd被置為1個(gè)報(bào)文段(256字節(jié)) 當(dāng)收到SYN和ACK時(shí),沒有對這兩個(gè)變量做任何修改,因?yàn)樾碌臄?shù)據(jù)還沒有被確認(rèn)。 當(dāng)ACK 257到達(dá)時(shí),因?yàn)閏wnd小于等于ssthresh,因此仍然處于慢啟動(dòng)階段,于是將cwnd增加256字節(jié)。當(dāng)收到ACK 513時(shí),進(jìn)行同樣的處理。 當(dāng)ACK 769到達(dá)時(shí),我們不再處于慢啟動(dòng)狀態(tài),而是進(jìn)入了擁塞避免狀態(tài)。新的cwnd值按以下方法計(jì)算: 通過上面公式計(jì)算獲得當(dāng)前cwnd的大小為885字節(jié): 當(dāng)下一個(gè)ACK 1025到達(dá)時(shí),我們計(jì)算cwnd為991字節(jié): 2)? 報(bào)文段丟失重傳 圖:報(bào)文段丟失重傳-擁塞避免例子 當(dāng)?shù)?個(gè)重復(fù)的ACK到達(dá)時(shí),ssthresh被置為cwnd的一半(四舍五入到報(bào)文段大小的下一個(gè)倍數(shù)),而cwnd被置為ssthresh加上所收到的重復(fù)的ACK數(shù)乘以報(bào)文段大小(也即1024加上3倍的256),然后發(fā)送重傳數(shù)據(jù)。 又有5個(gè)重復(fù)的ACK到達(dá)(報(bào)文段64~66, 68和70),每次cwnd增加1個(gè)報(bào)文段長度。最后一個(gè)新的ACK(報(bào)文段72段)到達(dá)時(shí),cwnd被置為ssthresh(1024)并進(jìn)入正常的擁塞避免過程。由于cwnd小于等于ssthresh(現(xiàn)在相等),因此報(bào)文段的大小增加到cwnd,取值為1280。 當(dāng)下一個(gè)新的ACK到達(dá)(沒有在圖中表示出來)時(shí),cwnd大于ssthresh,取值為1363: ?
? 在快速重傳和快速恢復(fù)階段,我們收到報(bào)文段66、68和70中的重復(fù)的ACK后才發(fā)送新的數(shù)據(jù),而不是在接收到報(bào)文段64和65中重復(fù)的ACK之后就發(fā)送。這是cwnd的取值與未被確認(rèn)的數(shù)據(jù)大小比較的結(jié)果。當(dāng)報(bào)文段65到達(dá)時(shí),cwnd為2048,但未被確認(rèn)的數(shù)據(jù)有2304字節(jié)(9個(gè)報(bào)文段:46, 48, 50, 52, 54, 55, 57, 59和63),因此不能發(fā)送任何數(shù)據(jù)。當(dāng)報(bào)文段65到達(dá)后,cwnd被置為2304,此時(shí)我們?nèi)圆荒苓M(jìn)行發(fā)送。但是當(dāng)報(bào)文段66到達(dá)時(shí),cwnd為2560,所以我們可以發(fā)送1個(gè)新的數(shù)據(jù)報(bào)文段。類似地,當(dāng)報(bào)文段68到達(dá)時(shí),cwnd等于2816,該數(shù)值大于未被確認(rèn)的2560字節(jié)的數(shù)據(jù)大小,因此我們可以發(fā)送另1個(gè)新的數(shù)據(jù)報(bào)文段。報(bào)文段70到達(dá)時(shí)也進(jìn)行了類似的處理。
? 5.? 重新分組 當(dāng)TCP超時(shí)并重傳時(shí),它不一定要重傳同樣的報(bào)文段。相反,TCP允許進(jìn)行重新分組而發(fā)送一個(gè)較大的報(bào)文段,這將有助于提高性能(當(dāng)然,這個(gè)較大的報(bào)文段不能夠超過接收方聲明的MSS)。在協(xié)議中這是允許的,因?yàn)門CP是使用字節(jié)序號而不是報(bào)文段序號來進(jìn)行識別它所要發(fā)送的數(shù)據(jù)和進(jìn)行確認(rèn)。
? 所謂字節(jié)流,是指TCP接收端并不知道發(fā)送端每次向該連接寫入了多少數(shù)據(jù),只關(guān)心通過限制能從連接中最大字節(jié)數(shù)。 二、協(xié)議格式 圖:TCP數(shù)據(jù)包結(jié)構(gòu) 圖:TCP包首部結(jié)構(gòu) 字段說明: 16位源端口號:指建立連接(或發(fā)送數(shù)據(jù))的端口號 16位目的端口號:指連接另一端(或接受數(shù)據(jù))的端口號 32位序號:發(fā)送的字節(jié)序號,如果是新建立的連接,則第一個(gè)包的seq為0,否則為上一個(gè)數(shù)據(jù)包的確認(rèn)序號。同一個(gè)包中的序號和確認(rèn)序號是不同的。 ? www.2cto.com ?
? 32位確認(rèn)序號:等于接收到數(shù)據(jù)包的序號seq+數(shù)據(jù)包的長度len。同時(shí)告訴對端,下一個(gè)數(shù)據(jù)包的開頭字節(jié)序號。 4位首部長度:tcp包首部的長度。 URG:緊急指針有效。它使一端可以告訴另一端有些具有某種方式的“緊急數(shù)據(jù)”已經(jīng)放置在普通的數(shù)據(jù)流中。另一端被通知這個(gè)緊急數(shù)據(jù)已被放置在普通數(shù)據(jù)流
? 中,由接收方?jīng)Q定如何處理。URG比特被置1,并且一個(gè)16bit的緊急指針被置為一個(gè)正的偏移量,該偏移量必須與TCP首部中的序號字段相加,以便得出緊急數(shù)據(jù)的最后一個(gè)字節(jié)的序號。注意:TCP的緊急方式不是帶外數(shù)據(jù)(out-of-band data)。緊急方式有什么作用呢?兩個(gè)最常見的例子是Telnet和Rlogin。當(dāng)交互用戶鍵入中斷鍵時(shí),另一個(gè)例子是FTP,當(dāng)交互用戶放棄一個(gè)文件的傳輸時(shí)。如果在接收方處理第一個(gè)緊急指針之前,發(fā)送方多次進(jìn)入緊急方式會發(fā)生什么情況呢?在數(shù)據(jù)流中的緊急指針會向前移動(dòng),而其在接收方的前一個(gè)位置將丟失。接收方只有一個(gè)緊急指針,每當(dāng)對方有新的值到達(dá)時(shí)它將被覆蓋。這意味著如果發(fā)送方進(jìn)入緊急方式時(shí)所寫的內(nèi)容對接收方非常重要,那么這些字節(jié)數(shù)據(jù)必須被發(fā)送方用某種方式特別標(biāo)記。我們將看到Telnet通過在數(shù)據(jù)流中加入一個(gè)值為255的字節(jié)作為前綴來標(biāo)記它所有的命令。 ? www.2cto.com ?
? ACK:確認(rèn)序號有效 PSH:接收方應(yīng)盡快將這個(gè)報(bào)文段交給應(yīng)用層。發(fā)送方使用PUSH標(biāo)志通知接收方將所收到的數(shù)據(jù)全部提交給接收進(jìn)程。這里的數(shù)據(jù)包括與PUSH一起傳送的數(shù)據(jù)以及接收方TCP已經(jīng)為接收進(jìn)程收到的其他數(shù)據(jù)(還在TCP的緩沖區(qū)中)。
? RST:重置連接 SYN:同步信號,用于發(fā)起一個(gè)連接 FIN:發(fā)端完成發(fā)送任務(wù),關(guān)閉連接 16位窗口大小:TCP的流量控制由連接的每一端通過聲明的窗口大小來提供。窗口大小為字節(jié)數(shù),起始于確認(rèn)序號字段指明的值,這個(gè)值是接收端正期望接收的字節(jié)。窗口大小是一個(gè)16 bit字段,因而窗口大小最大為65535字節(jié)。 ? www.2cto.com ?
? 16位校驗(yàn)和:檢驗(yàn)和覆蓋了整個(gè)的TCP報(bào)文段:TCP首部和TCP數(shù)據(jù)。 16位緊急指針:只有當(dāng)URG標(biāo)志置1時(shí)緊急指針才有效。緊急指針是一個(gè)正的偏移量,和序號字段中的值相加表示緊急數(shù)據(jù)最后一個(gè)字節(jié)的序號。TCP的緊急方式是發(fā)送端向另一端發(fā)送緊急數(shù)據(jù)的一種方式。 選項(xiàng):部分可選配置,主要有以下幾種: 每個(gè)選項(xiàng)的開始是1字節(jié)kind字段,說明選項(xiàng)的類型。kind字段為0和1的選項(xiàng)僅占1個(gè)字節(jié)。其他的選項(xiàng)在kind字節(jié)后還有l(wèi)en字節(jié)。它說明的長度是指總長度,包括kind字節(jié)和len字節(jié)。 ? www.2cto.com ? 三、TCP各種狀態(tài) 1. 狀態(tài)轉(zhuǎn)移 A?主動(dòng)建立連接 圖:主動(dòng)建立連接 B?被動(dòng)建立連接 圖:被動(dòng)建立連接 C?主動(dòng)關(guān)閉連接 圖:主動(dòng)關(guān)閉連接 D?被動(dòng)關(guān)閉連接 圖:被動(dòng)關(guān)閉連接 2. 建立連接 圖:TCP建立連接 3. 關(guān)閉連接 圖:TCP關(guān)閉連接 4. 半連接 TCP連接是個(gè)全雙工通道,所以可以同時(shí)支持發(fā)送和接收。可以認(rèn)為將一個(gè)通道分成兩部分,就像高速公路一樣,一條大路中間分隔,兩邊的方向完全相反。 半連接是指連接的一端發(fā)送完本地?cái)?shù)據(jù)后,將發(fā)送的那半個(gè)連接關(guān)閉,告訴對端不用再等待接收數(shù)據(jù),而對端照樣可以發(fā)送數(shù)據(jù),本端可以讀取數(shù)據(jù)。 再舉高速公路的例子,假如連接是北京到天津的高速公路,如果某一天,北京到天津方向的沒有車輛,則該方向高速公路可以封閉,北京這邊的入口將關(guān)閉,同時(shí)告知天津出口不會有車輛通行,天津出口也沒必要有人值班了。但是,有不少車輛要從天津開往北京方向,這樣天津的入口沒有關(guān)閉,北京的出口則需要有人收費(fèi)抬桿。
? 5. 復(fù)位報(bào)文 無論何時(shí)一個(gè)報(bào)文段發(fā)往基準(zhǔn)的連接(referenced connection)出現(xiàn)錯(cuò)誤,TCP都會發(fā)出一個(gè)復(fù)位報(bào)文段(這里提到的“基準(zhǔn)的連接”是指由目的I P地址和目的端口號以及源I P地址和源端口號指明的連接。) 產(chǎn)生復(fù)位的一種常見情況是當(dāng)連接請求到達(dá)時(shí),目的端口沒有進(jìn)程正在聽。對于UDP,當(dāng)一個(gè)數(shù)據(jù)報(bào)到達(dá)目的端口時(shí),該端口沒在使用,它將產(chǎn)生一個(gè)ICMP端口不可達(dá)的信息。而TCP則使用復(fù)位。
? 發(fā)送一個(gè)復(fù)位報(bào)文段而不是FIN來中途釋放一個(gè)連接,這稱為異常釋放。異常終止一個(gè)連接對應(yīng)用程序來說有兩個(gè)優(yōu)點(diǎn):(1)丟棄任何待發(fā)數(shù)據(jù)并立即發(fā)送復(fù)位報(bào)文段;(2)RST的接收方會區(qū)分另一端執(zhí)行的是異常關(guān)閉還是正常關(guān)閉。應(yīng)用程序使用的API必須提供產(chǎn)生異常關(guān)閉而不是正常關(guān)閉的手段。Socket API通過“l(fā)inger on close”選項(xiàng)(SO_LINGER)提供了這種異常關(guān)閉的能力。我們加上-L選項(xiàng)并將停留時(shí)間設(shè)為0。這將導(dǎo)致連接關(guān)閉時(shí)進(jìn)行復(fù)位而不是正常的FIN。 四、TCP數(shù)據(jù)傳輸 1. 正常傳輸 圖:正常的數(shù)據(jù)傳輸 2. 快發(fā)慢接 圖:快發(fā)到慢收的數(shù)據(jù)傳輸 上圖說明,在慢收設(shè)備接收數(shù)據(jù)時(shí),由于沒有及時(shí)的將TCP緩沖區(qū)的數(shù)據(jù)讀到應(yīng)用層而會返回給發(fā)送端一個(gè)通告窗口為0的ACK。 五、超時(shí)和重傳機(jī)制 1. 往返時(shí)間RTT及重傳超時(shí)間RTO(Retransmission TimeOut) RTT估計(jì)器:R←aR+ ( 1-a )M 這里的a是一個(gè)推薦值為0.9的平滑因子。每次進(jìn)行新測量的時(shí)候,這個(gè)被平滑的RTT將得到更新。每個(gè)新估計(jì)的90%來自前一個(gè)估計(jì),而10 %則取自新的測量。 RTO公式: E rr= M-A A←A+ g E rr D←D+ h( | E rr |-D) RTO= A+ 4D 這里的A是被平滑的RTT(均值的估計(jì)器)而D則是被平滑的均值偏差。Err是剛得到的測量結(jié)果與當(dāng)前的RTT估計(jì)器之差。A和D均被用于計(jì)算下一個(gè)重傳時(shí)間(RTO)。增量g起平均作用,取為1/8(0.125)。偏差的增益是h,取值為0.25。當(dāng)RTT變化時(shí),較大的偏差增益將使RTO快速上升。 一個(gè)TCP連接只有一個(gè)RTT計(jì)時(shí)器,如果一個(gè)請求發(fā)送時(shí)計(jì)時(shí)器已經(jīng)開始計(jì)時(shí),則該請求不進(jìn)行RTT計(jì)算。 圖:RTT計(jì)時(shí) 上圖中,第4個(gè)數(shù)據(jù)包在發(fā)送時(shí)因?yàn)镽TT計(jì)時(shí)器已經(jīng)開始計(jì)時(shí)(第3個(gè)數(shù)據(jù)包)而沒有再次啟動(dòng)計(jì)時(shí)器。 2.? 擁塞避免算法 有兩種分組丟失的指示:發(fā)生超時(shí)和接收到重復(fù)的確認(rèn)。 擁塞避免算法和慢啟動(dòng)算法是兩個(gè)目的不同、獨(dú)立的算法。但是當(dāng)擁塞發(fā)生時(shí),我們希望降低分組進(jìn)入網(wǎng)絡(luò)的傳輸速率,于是可以調(diào)用慢啟動(dòng)來作到這一點(diǎn)。 擁塞避免算法和慢啟動(dòng)算法需要對每個(gè)連接維持兩個(gè)變量:一個(gè)擁塞窗口cwnd和一個(gè)慢啟動(dòng)門限ssthresh。算法如下: 1)? 對一個(gè)給定的連接,初始化cwnd為1個(gè)報(bào)文段,ssthresh為65535個(gè)字節(jié)。 2)? TCP輸出例程的輸出不能超過cwnd和接收方通告窗口的大小。擁塞避免是發(fā)送方使用的流量控制,而通告窗口則是接收方進(jìn)行的流量控制。前者是發(fā)送方感受到的網(wǎng)絡(luò)擁塞的估計(jì),而后者則與接收方在該連接上的可用緩存大小有關(guān)。 3)? 當(dāng)擁塞發(fā)生時(shí)(超時(shí)或收到重復(fù)確認(rèn)),ssthresh被設(shè)置為當(dāng)前窗口大小的一半(cwnd和接收方通告窗口大小的最小值,但最少為2個(gè)報(bào)文段)。此外,如果是超時(shí)引起了擁塞,則cwnd被設(shè)置為1個(gè)報(bào)文段(這就是慢啟動(dòng))。
? 4)? 當(dāng)新的數(shù)據(jù)被對方確認(rèn)時(shí),就增加cwnd,但增加的方法依賴于我們是否正在進(jìn)行慢啟動(dòng)或擁塞避免。如果cwnd小于或等于ssthresh,則正在進(jìn)行慢啟動(dòng),否則正在進(jìn)行擁塞避免。慢啟動(dòng)一直持續(xù)到我們回到當(dāng)擁塞發(fā)生時(shí)所處位置的半時(shí)候才停止(因?yàn)槲覀冇涗浟嗽诓襟E2中給我們制造麻煩的窗口大小的一半),然后轉(zhuǎn)為執(zhí)行擁塞避免。 慢啟動(dòng)算法初始設(shè)置cwnd為1個(gè)報(bào)文段,此后每收到一個(gè)確認(rèn)就加1。 擁塞避免算法要求每次收到一個(gè)確認(rèn)時(shí)將cwnd增加1/cwnd。與慢啟動(dòng)的指數(shù)增加比起來,這是一種加性增長(additive increase)。我們希望在一個(gè)往返時(shí)間內(nèi)最多為cwnd增加1個(gè)報(bào)文段(不管在這個(gè)RTT中收到了多少個(gè)ACK),然而慢啟動(dòng)將根據(jù)這個(gè)往返時(shí)間中所收到的確認(rèn)的個(gè)數(shù)增加cwnd。 圖:慢啟動(dòng)和擁塞避免的可視化描述 3.? 快速重傳與快速恢復(fù)算法 在收到一個(gè)失序的報(bào)文之后,TCP需要立即產(chǎn)生一個(gè)ACK(一個(gè)重復(fù)的ACK)。這個(gè)ACK不應(yīng)該被延遲。該重復(fù)的ACK是為了讓對方知道收到一個(gè)失序的報(bào)文段,并告訴對方自己希望收到的報(bào)文序號。 問題出現(xiàn)了,有兩種可能我們會收到重復(fù)的ACK:丟包和報(bào)文段失序。如果是報(bào)文段失序了,那么在發(fā)送一兩個(gè)重復(fù)的ACK之后,基本上都能接收到失序的幾個(gè)報(bào)文,然后在TCP緩沖區(qū)中重新排序,然后返回另一個(gè)ACK(希望收到的下一個(gè)報(bào)文的序號);而如果有三個(gè)或三個(gè)以上的重復(fù)ACK,那么認(rèn)為該ACK對應(yīng)的數(shù)據(jù)已經(jīng)丟失,需要立即進(jìn)行重傳,無需等待超時(shí)定時(shí)器溢出。這就是快速重傳算法。 圖:TCP超時(shí)重傳 上圖可以看出,發(fā)送端在連續(xù)收到了3個(gè)重復(fù)的ACK報(bào)文后,并沒有進(jìn)入慢啟動(dòng),而是執(zhí)行了擁塞避免算法,這就是快速回復(fù)算法。之所以沒有執(zhí)行慢啟動(dòng)算法是因?yàn)?#xff0c;發(fā)送端收到了連續(xù)的重復(fù)的ACK報(bào)文段后,不僅判斷出這個(gè)報(bào)文已經(jīng)丟失,還能判斷到接收端收到了后面的幾個(gè)報(bào)文段(只有這樣,接收端才連續(xù)的返回重復(fù)ACK報(bào)文),表明這時(shí)候的網(wǎng)絡(luò)仍然可以傳輸報(bào)文,沒有必要執(zhí)行慢啟動(dòng)影響傳輸性能,所以,在接收到重傳報(bào)文段的ACK之前,又發(fā)出了三個(gè)報(bào)文段67、69和71。
? 這個(gè)算法通常按如下過程進(jìn)行實(shí)現(xiàn): 1) 當(dāng)收到第3個(gè)重復(fù)的ACK時(shí),將ssthresh設(shè)置為當(dāng)前擁塞窗口cwnd的一半。重傳丟失的報(bào)文段。設(shè)置cwnd為ssthresh加上3倍的報(bào)文段大小。 2) 每次收到另一個(gè)重復(fù)的ACK時(shí),cwnd增加1個(gè)報(bào)文段大小并發(fā)送1個(gè)分組(如果新的cwnd允許發(fā)送)。 3) 當(dāng)下一個(gè)確認(rèn)新數(shù)據(jù)的A C K到達(dá)時(shí),設(shè)置cwnd為ssthresh(在第1步中設(shè)置的值)。這個(gè)ACK應(yīng)該是在進(jìn)行重傳后的一個(gè)往返時(shí)間內(nèi)對步驟1中重傳的確認(rèn)。另外,這個(gè)ACK也應(yīng)該是對丟失的分組和收到的第1個(gè)重復(fù)的ACK之間的所有中間報(bào)文段的確認(rèn)。這一步采用的是擁塞避免,因?yàn)楫?dāng)分組丟失時(shí)我們將當(dāng)前的速率減半。 4.? 擁塞算法例子 1)? 初始SYN有一個(gè)超時(shí)重傳的例子 ?圖:SYN超時(shí)重傳-擁塞避免例子 當(dāng)SYN的超時(shí)發(fā)生時(shí),sstresh被置為其最小取值(512字節(jié),表示2個(gè)報(bào)文段)。為進(jìn)入慢啟動(dòng)階段,cwnd被置為1個(gè)報(bào)文段(256字節(jié)) 當(dāng)收到SYN和ACK時(shí),沒有對這兩個(gè)變量做任何修改,因?yàn)樾碌臄?shù)據(jù)還沒有被確認(rèn)。 當(dāng)ACK 257到達(dá)時(shí),因?yàn)閏wnd小于等于ssthresh,因此仍然處于慢啟動(dòng)階段,于是將cwnd增加256字節(jié)。當(dāng)收到ACK 513時(shí),進(jìn)行同樣的處理。 當(dāng)ACK 769到達(dá)時(shí),我們不再處于慢啟動(dòng)狀態(tài),而是進(jìn)入了擁塞避免狀態(tài)。新的cwnd值按以下方法計(jì)算: 通過上面公式計(jì)算獲得當(dāng)前cwnd的大小為885字節(jié): 當(dāng)下一個(gè)ACK 1025到達(dá)時(shí),我們計(jì)算cwnd為991字節(jié): 2)? 報(bào)文段丟失重傳 圖:報(bào)文段丟失重傳-擁塞避免例子 當(dāng)?shù)?個(gè)重復(fù)的ACK到達(dá)時(shí),ssthresh被置為cwnd的一半(四舍五入到報(bào)文段大小的下一個(gè)倍數(shù)),而cwnd被置為ssthresh加上所收到的重復(fù)的ACK數(shù)乘以報(bào)文段大小(也即1024加上3倍的256),然后發(fā)送重傳數(shù)據(jù)。 又有5個(gè)重復(fù)的ACK到達(dá)(報(bào)文段64~66, 68和70),每次cwnd增加1個(gè)報(bào)文段長度。最后一個(gè)新的ACK(報(bào)文段72段)到達(dá)時(shí),cwnd被置為ssthresh(1024)并進(jìn)入正常的擁塞避免過程。由于cwnd小于等于ssthresh(現(xiàn)在相等),因此報(bào)文段的大小增加到cwnd,取值為1280。 當(dāng)下一個(gè)新的ACK到達(dá)(沒有在圖中表示出來)時(shí),cwnd大于ssthresh,取值為1363: ?
? 在快速重傳和快速恢復(fù)階段,我們收到報(bào)文段66、68和70中的重復(fù)的ACK后才發(fā)送新的數(shù)據(jù),而不是在接收到報(bào)文段64和65中重復(fù)的ACK之后就發(fā)送。這是cwnd的取值與未被確認(rèn)的數(shù)據(jù)大小比較的結(jié)果。當(dāng)報(bào)文段65到達(dá)時(shí),cwnd為2048,但未被確認(rèn)的數(shù)據(jù)有2304字節(jié)(9個(gè)報(bào)文段:46, 48, 50, 52, 54, 55, 57, 59和63),因此不能發(fā)送任何數(shù)據(jù)。當(dāng)報(bào)文段65到達(dá)后,cwnd被置為2304,此時(shí)我們?nèi)圆荒苓M(jìn)行發(fā)送。但是當(dāng)報(bào)文段66到達(dá)時(shí),cwnd為2560,所以我們可以發(fā)送1個(gè)新的數(shù)據(jù)報(bào)文段。類似地,當(dāng)報(bào)文段68到達(dá)時(shí),cwnd等于2816,該數(shù)值大于未被確認(rèn)的2560字節(jié)的數(shù)據(jù)大小,因此我們可以發(fā)送另1個(gè)新的數(shù)據(jù)報(bào)文段。報(bào)文段70到達(dá)時(shí)也進(jìn)行了類似的處理。
? 5.? 重新分組 當(dāng)TCP超時(shí)并重傳時(shí),它不一定要重傳同樣的報(bào)文段。相反,TCP允許進(jìn)行重新分組而發(fā)送一個(gè)較大的報(bào)文段,這將有助于提高性能(當(dāng)然,這個(gè)較大的報(bào)文段不能夠超過接收方聲明的MSS)。在協(xié)議中這是允許的,因?yàn)門CP是使用字節(jié)序號而不是報(bào)文段序號來進(jìn)行識別它所要發(fā)送的數(shù)據(jù)和進(jìn)行確認(rèn)。
轉(zhuǎn)載于:https://www.cnblogs.com/fvsfvs123/p/4362567.html
總結(jié)
以上是生活随笔為你收集整理的TCP协议的一些认识及实践的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 设计模式 笔记 命令模式 Command
- 下一篇: bizagi simulation 仿真