TCP/IP協(xié)議
作者:xinyuans
本文為參考TCP/IP詳解卷一仑最,某些知識點加上了作者自己的理解尖昏,如有錯誤,歡迎指正倦畅,可以聯(lián)系我!
TCP包格式和IP包格式如下:
建立連接
TCP協(xié)議提供可靠的面向連接服務(wù)驰弄,采用三次握手建立連接麻汰。
第一次握手:建立連接時,客戶端發(fā)送SYN包(syn=j)到服務(wù)器戚篙,并進入SYN_SEND狀態(tài)五鲫,等待服務(wù)器確認(rèn);
第二次握手:服務(wù)器收到SYN包岔擂,向客戶端返回ACK(ack=j+1)位喂,同時自己也發(fā)送一個SYN包(syn=k),即SYN+ACK包智亮,此時服務(wù)器進入SYN_RCVD狀態(tài)忆某;
第三次握手:客戶端收到服務(wù)器的SYN+ACK包,向服務(wù)器發(fā)送確認(rèn)包ACK(ack=k+1)阔蛉,此包發(fā)送完畢弃舒,客戶端和服務(wù)器進入ESTABLISHED狀態(tài),完成三次握手状原。
完成三次握手聋呢,客戶端與服務(wù)器開始傳送數(shù)據(jù),也就是ESTABLISHED狀態(tài)颠区。
終止連接
采用四次揮手?jǐn)嚅_雙向連接削锰。
(1) TCP客戶端發(fā)送一個FIN,用來關(guān)閉客戶到服務(wù)器的數(shù)據(jù)傳送毕莱。
(2) 服務(wù)器收到這個FIN器贩,它發(fā)回一個ACK,確認(rèn)序號為收到的序號加1朋截。和SYN一樣蛹稍,一個FIN將占用一個序號。
(3) 服務(wù)器關(guān)閉客戶端的連接部服,發(fā)送一個FIN給客戶端唆姐。
(4) 客戶端發(fā)回ACK報文確認(rèn),并將確認(rèn)序號設(shè)置為收到序號加1廓八。
TCP狀態(tài)變遷圖
客戶端的狀態(tài)可以用一下流程圖來表示:
CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED
服務(wù)器的狀態(tài)可以流程圖:
CLOSED->LISTEN->SYN收到 ->ESTABLISHED->CLOSE_WAIT->LAST->ACK->CLOSED
2MSL等待狀態(tài)(兩個作用)
TIME_WAIT狀態(tài)也稱為2MSL等待狀態(tài)奉芦。每個具體TCP實現(xiàn)必須選擇一個報文段最大生存時間MSL(Maximum Segment Lifetime)赵抢。它是任何報文段被丟棄前在網(wǎng)絡(luò)內(nèi)的最長時間。處理原則:當(dāng)TCP執(zhí)行一個主動關(guān)閉声功,并發(fā)回最后一個ACK烦却,該鏈接必須在TIME_WAIT狀態(tài)停留的時間為2MSL。這樣可讓TCP有機會在此發(fā)送最后一個ACK以防這個ACK丟失(在另一端發(fā)送FIN前提)
但是减噪,在連接處于2MSL等待時短绸,任何遲到返回的報文段將被丟棄车吹。因為處于2MSL等待的筹裕、由該插口對(socket pair)定義的連接在這段時間內(nèi)不能被再用,對于客戶程序還好 一些窄驹,但是對于服務(wù)程序朝卒,例如httpd,它總是要使用同一個端口80來進行服務(wù)乐埠,而在 2MSL時間內(nèi)抗斤,啟動httpd就會出現(xiàn)錯誤(插口被使用)。為了避免這個錯誤丈咐,服務(wù)器給出了一個平靜時間(quit time)的概念瑞眼,這是說在2MSL時間內(nèi),雖然可以重新啟動服務(wù)器棵逊,但是這個服務(wù)器還是要平靜等待MSL時間才能進行下一次連接伤疙,讓后來返回的數(shù)據(jù)包沒有機會影響到發(fā)送端,因為返回的包和重新建立的包使用同一個四元組辆影,發(fā)送端無法區(qū)分這兩個包屬于不同連接徒像。(建議MSL時間為2min,不過這個與操作系統(tǒng)有關(guān)蛙讥。)
半打開狀態(tài)(Half-Open)
如果以防已經(jīng)關(guān)閉或異常終止連接而另一方卻不知道锯蛀,我們將這樣的TCP連接稱為半打開的。這種狀態(tài)可以通過Keepalive選項來進行發(fā)現(xiàn)兩一段已經(jīng)消失次慢。還有一種形式是:本端發(fā)送SYN旁涤,對端回應(yīng)ACK+SYN,此時本段不回應(yīng)ACK迫像。
當(dāng)處于半打開狀態(tài)的一方重啟并重新連接后劈愚,它將丟失復(fù)位前的所有信息,因此它并不知道數(shù)據(jù)報文段中提到的連接侵蒙。此時就會返回RST(異常終止要發(fā)送RST置位的包)包應(yīng)答造虎,已關(guān)閉此次連接。此時只需要等待MSL時間纷闺,因為TCP默認(rèn)機器重啟的時間大于MSL算凿。PIX防火墻和IDS入侵檢測系統(tǒng)都可以偽裝攻擊目標(biāo)發(fā)送RST的包去終止異常的TCP連接份蝴。(比如限定連接的時間,減少半開連接限制超時時間)當(dāng)我們Telnet一個不存在的端口號時氓轰,本段立馬收到一個拒絕訪問的包婚夫,這個就是對方發(fā)送的RST包導(dǎo)致的。
半關(guān)閉狀態(tài)(Half-Close)
單方向鏈路關(guān)閉署鸡。即TCP連接一端在結(jié)束它的發(fā)送后還能接收來自另一端數(shù)據(jù)的能力案糙。程序調(diào)用的是shutdown,而不是close靴庆,不過大多數(shù)程序都是調(diào)用close終止兩個方向的連接时捌。
最大報文段長度MSS(Option字段)
最大報文段長度表示TCP傳往另一端的最大塊數(shù)據(jù)的長度。當(dāng)建立一個連接時炉抒,每一方都受到對方通告的MSS值(MSS選項只能出現(xiàn)在SYN報文中)奢讨。如果一方收不到另一方的MSS值,那么就設(shè)為默認(rèn)的536字節(jié)焰薄。MSS是最長見的選項字段拿诸,還有另一個選項叫做窗口放大因子(Window*Shift Count即可以發(fā)送超大的數(shù)據(jù)包,即乘以目前窗口的倍數(shù)為實際一次發(fā)送的數(shù)據(jù)量塞茅。解決高速鏈路和高速主機普通TCP發(fā)包過慢問題亩码。)。還有一些HASH值也會放在Option字段野瘦。而防火墻默認(rèn)則會清掉IP和TCP的Option選項字段描沟。
網(wǎng)絡(luò)中某個應(yīng)用程序不斷地送出小單位的資料,且某些常是1字節(jié)大小缅刽。因為TCP封包具有40字節(jié)的總頭部(加上20字節(jié)的IP頭部)啊掏,這導(dǎo)致41字節(jié)大小的包只有一字節(jié)的數(shù)據(jù),這造成了極大的資源浪費衰猛,更糟糕的是在慢速網(wǎng)絡(luò)下迟蜜,這類包造成擁塞碰撞(Congestion Collapse)。TCP連接最多只能有一個未被確認(rèn)的小分組啡省。只適用于低速鏈路娜睛。
Nagle算法過程:
1.發(fā)送端TCP將它從發(fā)送應(yīng)用程序收到的第一個數(shù)據(jù)發(fā)送出去,哪怕只有一個字節(jié)卦睹;
2.在發(fā)送出第一個報文段后畦戒,發(fā)送端的TCP數(shù)據(jù)包就會在輸出緩存中積累并等待,當(dāng)從接收端收到對上一個數(shù)據(jù)包的ACK或者緩存中積累到一個最大報文段后结序,發(fā)送端TCP就可以發(fā)送這個報文段了障斋。
Nagle算法的優(yōu)點就是簡單,并且它考慮到應(yīng)用程序產(chǎn)生數(shù)據(jù)的速率,以及網(wǎng)絡(luò)運輸數(shù)據(jù)的速率垃环。若應(yīng)用程序比網(wǎng)絡(luò)更快邀层,則報文段就更大(最大報文段)。若應(yīng)用程序比網(wǎng)絡(luò)慢遂庄,則報文段就較辛仍骸(小于最大報文段)。
不過有時候我們必須要關(guān)閉納格算法的:比鼠標(biāo)的移動涛目,這個必須無時延的發(fā)送秸谢;還有功能鍵的發(fā)送,比如F1發(fā)送的不止一個字符霹肝,此時就不能啟用納格算法估蹄。
通常TCP在接收到數(shù)據(jù)時并不立即發(fā)送ACK;相反阿迈,它推遲發(fā)送元媚,以便將ACK與需要沿該方向發(fā)送的數(shù)據(jù)一起發(fā)送(有時稱這種現(xiàn)象為數(shù)據(jù)捎帶ACK)轧叽。絕大多數(shù)實驗為200ms)也就是說苗沧,TCP將以最大200ms的時延等待是否有屬于一起發(fā)送。
一個例子:這里我們將舉另外一個例子:在一個交互注冊過程中鍵入中斷的一個特殊功能鍵炭晒。這個功能鍵通炒眩可以產(chǎn)生多個字符序列,經(jīng)常從ASCII碼的轉(zhuǎn)移(escape)字符開始网严,如果TCP每次得到一個字符识樱,它很可能會發(fā)送序列中的第一個字符(ASCII碼的ESC),然后緩存其他字符并等待對該字符的確認(rèn)震束。但當(dāng)服務(wù)器收到該字符后怜庸,它并不發(fā)送確認(rèn)而是繼續(xù)的等待接受序列中的其他字符。這就會經(jīng)常觸發(fā)服務(wù)器的經(jīng)受時延的確認(rèn)算法垢村,表示剩下的字符沒有在200ms內(nèi)發(fā)送割疾。對于交互用戶而言,這將產(chǎn)生明顯的時延嘉栓。
注意只有客戶端這邊有經(jīng)受時延的確認(rèn)宏榕,因為客戶端這邊輸入的比較慢,服務(wù)器那邊收到數(shù)據(jù)就會立即確認(rèn)侵佃。最大等待200ms還沒有數(shù)據(jù)發(fā)送的話麻昼,客戶端就直接返回ACK了。
滑動窗口
TCP采用滑動窗口來進行傳輸控制馋辈,滑動窗口的大小意味著接收方有多大的緩存區(qū)可以用于接收數(shù)據(jù)抚芦。發(fā)送方可以通過滑動窗口的大小來確定應(yīng)該發(fā)送多少字節(jié)的數(shù)據(jù)。當(dāng)滑動窗口為0時,發(fā)送方一般不能再發(fā)送數(shù)據(jù)叉抡,但是緊急數(shù)據(jù)除外枢劝,例如:允許用戶終止在遠(yuǎn)端機上的運行進程。另一種情況是發(fā)送方可以發(fā)送一個1字節(jié)的數(shù)據(jù)報來通知接收方重新聲明它希望接收的下一字節(jié)及發(fā)送方的滑動窗口大小卜壕。
滑動窗口機制的基本原理就是在任意時刻您旁,發(fā)送方都維持了一個連續(xù)的允許發(fā)送的幀的序號,稱為發(fā)送窗口轴捎,同時鹤盒,接收方也維持了一個允許接收的幀的序號,稱為接收窗口侦副。發(fā)送窗口和接收窗口的序號的上下界不一定要一樣侦锯,甚至大小也可不同。不同的滑動窗口協(xié)議窗口大小一般不同秦驯。發(fā)送窗口內(nèi)的序號的上下界不一定要一樣尺碰,但是還沒有被確認(rèn)的幀,或者是哪些可以被發(fā)送的幀译隘。
稱窗口左邊向右邊靠近為窗口合攏亲桥。這種現(xiàn)象發(fā)生在數(shù)據(jù)被發(fā)送和確認(rèn)時。
當(dāng)窗口右邊沿想右移動時將允許發(fā)送更多的數(shù)據(jù)固耘,我們稱之為窗口張開题篷。這種先發(fā)發(fā)送在另一端的接收進程讀取已經(jīng)確認(rèn)的數(shù)據(jù)并釋放了TCP的接收緩存時。
當(dāng)右邊裝口左移時厅目,我們稱之為窗口收縮番枚。
發(fā)送方打開幾號窗口表示發(fā)送方已經(jīng)發(fā)送了該序列的幀,但是如果沒有得到接收方ack確認(rèn)的話损敷,此時該序號的幀仍然在發(fā)送窗口中葫笼。接收方方打開幾號窗口代表接收端收到幾號的幀,但是并沒有返回ack確認(rèn)拗馒。當(dāng)接收方返回該序號的ack時路星,該序號關(guān)閉(合攏),接收方收到ack時瘟忱,該序號窗口關(guān)閉(此時窗口張開奥额,注意始終不能大于通告窗口大小)访诱。
對于發(fā)送窗口來說窗口打開代表發(fā)送了該序列數(shù)據(jù)垫挨,但沒有收到確認(rèn),收到ACK后窗口合攏触菜。
對于接受窗口來說窗口打開代表接受了該序列數(shù)據(jù)九榔,但沒有發(fā)送確認(rèn),當(dāng)發(fā)ACK后窗口合攏。
1比特滑動窗口協(xié)議
當(dāng)發(fā)送窗口和接收窗口的大小固定為1時哲泊,滑動窗口協(xié)議退化為停等協(xié)議(stop-and-wait)剩蟀。該協(xié)議規(guī)定發(fā)送方每發(fā)送一幀后就要停下來,等待接收方已正確接收的確認(rèn)(Acknowledgement)返回后才能繼續(xù)發(fā)送下一個幀切威。由于發(fā)送方需要判斷接收到的幀是新習(xí)發(fā)的幀還是重新發(fā)送的幀育特,因此發(fā)送放要為每個幀加一個序號。由于停等協(xié)議規(guī)定只要一幀完全發(fā)送成功后才能發(fā)送新的幀先朦,因而只用一比特來編號就夠了缰冤。
后退n協(xié)議
由于停等協(xié)議要為每一個幀進行確認(rèn)后才繼續(xù)發(fā)送下一幀,大大降低了信道利用率喳魏,因此又提出了后退n協(xié)議棉浸。后退n協(xié)議中,發(fā)送方在發(fā)完已給數(shù)據(jù)幀后 刺彩,不停下來等待應(yīng)答幀迷郑,而是連續(xù)發(fā)送若干個幀,即使在連續(xù)發(fā)送過程中收到了接收方發(fā)來的應(yīng)答幀创倔,也可以繼續(xù)發(fā)送嗡害。且發(fā)送方在每發(fā)完一個數(shù)據(jù)幀時都要設(shè)置超時定時器。只要在所設(shè)置的超時時間內(nèi)未收到確認(rèn)幀三幻,就要重發(fā)相應(yīng)的數(shù)據(jù)幀就漾。如:當(dāng)發(fā)送方發(fā)送了N個幀后,若發(fā)現(xiàn)該N幀的前一個幀在計時器超后仍未返回其確認(rèn)信息念搬,該幀被判定為出錯或者丟失,此時發(fā)送方就不得不重新發(fā)送出錯幀及其后的N幀摆出。
從這里不難看出朗徊,后退n協(xié)議一方面因連續(xù)發(fā)送數(shù)據(jù)幀而提高了效率,但是另一方面偎漫,在重傳時又必須把原已正確重傳的數(shù)據(jù)幀進行重傳(僅因這些數(shù)據(jù)這之前有一個數(shù)據(jù)幀出錯)爷恳,這種做法又使重傳效率降低。由此可見象踊,若傳輸信道的傳輸質(zhì)量很差因而導(dǎo)致誤碼率較大温亲,連續(xù)測協(xié)議不一定優(yōu)于停止等待協(xié)議。此協(xié)議中的發(fā)送窗口的大小為k杯矩,接收窗口仍未1.
選擇重傳協(xié)議
在后退n協(xié)議中栈虚,接收方若發(fā)現(xiàn)錯誤幀就不再接收后續(xù)的幀,及時是正確的幀到達史隆,這顯然是一種浪費魂务。另一種效率跟高的策略是當(dāng)接收方發(fā)現(xiàn)某幀出錯后,其后繼續(xù)送來的正確的幀雖然不能立即遞交給接收方的高層,但接收方扔可收下來粘姜,存放在一個緩沖區(qū)鬓照,同時要求發(fā)送方重新傳輸出錯的那一幀。一旦收到重新傳來的幀后孤紧,就可以源存與緩沖區(qū)中國的其余幀一并按正確的順序遞交高層豺裆。這種方法稱為選擇重發(fā)(Selectice Repeat),顯然号显,選擇重發(fā)減少了浪費留储,但要求接收方有足夠大的緩沖區(qū)空間。
當(dāng)發(fā)送端應(yīng)用程序產(chǎn)生數(shù)據(jù)很慢咙轩、或者接收端應(yīng)用程序處理接收緩存區(qū)的數(shù)據(jù)很慢的時候获讳,就會在鏈路中傳送很小的報文段,極端情況下有小負(fù)載只有1字節(jié)而報文段卻又41字節(jié)活喊。這種現(xiàn)象叫做糊涂窗口綜合癥(Silly Window Syndrome)丐膝。
可以在發(fā)送方或接收方任意一方采取措施來避免這種現(xiàn)象
在接收端避免措施
接收方不通告小窗口,通常算法是接收方不通告一個比當(dāng)前窗口大的窗口除非窗口可以增加一個報文段大屑鼐铡(將要接收MSS的大兴Т!)、或者可以在增加接收方緩存空間的一半煞烫。
在發(fā)送端避免措施
發(fā)送方在滿足一下條件之一后才會發(fā)送數(shù)據(jù):1.可以發(fā)送一個滿長度的報文段浑此;2.可以發(fā)送至少是接收方通告窗口大小一半的報文段;3.能夠發(fā)送手頭的所有數(shù)據(jù)并且不希望接收ACK或者改連接禁用了納格算法滞详。
如果發(fā)送方一開始便向網(wǎng)絡(luò)發(fā)送多個報文段凛俱,知道達到接收方通告的窗口大小為止。當(dāng)發(fā)送方和接收方位于同一局域網(wǎng)還好料饥。但是如果發(fā)送方和接收方之間存在多個路由器和速率較慢的鏈路時蒲犬,可能出現(xiàn)問題。中間的路由器必須緩存分組岸啡,并有可能耗盡存儲器的空間≡#現(xiàn)在TCP支持一種被稱為“慢啟動(slow start)”的算法。該算法核心是讓新分組進入網(wǎng)絡(luò)的速率與另一端返回確認(rèn)的速率相同而進行工作巡蘸。
慢啟動為發(fā)送方的TCP增加了另一窗口:擁塞窗口(congestion window奋隶,cwnd)當(dāng)與另一個網(wǎng)絡(luò)的主機建立TCP連接時,擁塞窗口被初始化為1個報文段悦荒。每收到一個ACK唯欣,擁塞窗口就增加一個報文段。以此成指數(shù)增長方式逾冬。發(fā)送方取擁塞窗口和通告窗口的最小值作為發(fā)送上限黍聂。擁塞窗口是發(fā)送方使用的流量控制躺苦,而通告窗口則是接收方使用的流量控制。
TCP超時重傳采用指數(shù)退避的算法(exponential backoff)對連續(xù)重傳之間不同的時間差产还,他們?nèi)≌蠓謩e為1\3\6\12\24\48\64(最大值為64)
擁塞算法是一種處理丟失分組的方法匹厘。網(wǎng)絡(luò)發(fā)生分組丟失的指示:發(fā)生超時和收到重復(fù)的ACK(3個或3個以上)
擁塞避免算法和慢啟動算法是兩個目的不同、獨立的算法脐区。但是方發(fā)生擁塞時愈诚,我們下午給你降低分組進入網(wǎng)絡(luò)的傳輸速率,于是可以調(diào)用慢啟動來作到這一點牛隅。在實際中這兩個算法通常在一起使用炕柔。
擁塞避免算法和慢啟動算法需要對每個連接維持兩個變量:一個擁塞窗口(cwnd)和一個慢啟動門限(ssthresh)。這樣得到的算法的工作過程如下:
1)對一個給定的連接媒佣,初始化cwnd為1個報文段匕累,ssthresh為65535個字節(jié);
2)TCP輸出數(shù)據(jù)大小不能超過cwnd和接收方通告窗口的大小。擁塞避免是發(fā)送方使用的流量控制,而通告窗口是接收方進行的流量控制富纸。前置是發(fā)送方感受到網(wǎng)絡(luò)擁塞的估計娘侍,后者則與接收方在該連接上的可用緩存大小有關(guān)辫封;
3)當(dāng)擁塞發(fā)生時(超時或收到重復(fù)確認(rèn)),ssthresh被設(shè)置為當(dāng)前窗口的一半,但至少為2個報文段大小。如果是超時引起的擁塞掐隐,則cwnd被設(shè)置為1個報文段(這就是慢啟動);
4)當(dāng)新的數(shù)據(jù)被對方確實時钞馁,就增加cwnd虑省,但增加的方法依賴于我們是否在進行慢啟動或擁塞避免。如果cwnd≤ssthresh指攒,則正在進行慢啟動慷妙,反之進行擁塞避免。慢啟動一直持續(xù)到我們我們回到當(dāng)擁塞發(fā)生時所處位置一半的時候才停止(即新的ssthresh)然后轉(zhuǎn)為執(zhí)行擁塞避免允悦。
慢啟動算法初始cwnd為1個報文段,每收到一個ack后cwnd就增加1(注意TCP是累計確認(rèn))虑啤,那樣隙弛,窗口會以指數(shù)方式增長。
擁塞避免算法要求每次收到確認(rèn)時將cwnd增加1/cwnd狞山,這是個線性增長全闷。我們希望在一個往返時間內(nèi)最多為cwnd增加1個報文段,不管在這個RTT中收到了多少個ACK萍启,然后慢啟動則是根據(jù)這個往返時間中所收到的確認(rèn)的個數(shù)增加cwnd总珠。
下圖是慢啟動和擁塞避免的可視化描述
解釋:上圖中屏鳍,假定當(dāng)cwnd為32個報文段時就會發(fā)生擁塞。于是設(shè)置ssthresh為16個報文段局服,而cwnd為1個報文段钓瞭。在時刻0發(fā)送一個報文段,并假設(shè)在時刻1接收到它的ACK淫奔,此時cwnd增加為2.接著發(fā)送了2個報文段山涡,并假設(shè)在時刻2接收到他們的ACK,于是cwnd增加為4(對每個ACK增加1次)唆迁。這種指數(shù)增加算法一直進行到在時刻3和時刻4之間收到8個ACK后cwnd等于ssthresh時才停止鸭丛,從該時刻起,cwnd以線性方式增加唐责,在每個往返時間內(nèi)最多增加1個報文段鳞溉。
正如我們在這個圖中看到的那樣,術(shù)語“慢啟動”并不完全正確鼠哥。它只是采用了比引起擁塞更慢的分組傳輸速率熟菲,但在慢啟動期間進入網(wǎng)絡(luò)分組速率依然是增加的。只有在達到ssthresh擁塞避免算法起作用時肴盏,這種增加的速率才會慢下來科盛。
算法通常按如下過程進行實現(xiàn):
1)當(dāng)收到第3個重復(fù)的ACK時,將ssthresh設(shè)置為當(dāng)前cwnd的一半菜皂。重傳丟失的報文段贞绵。然后設(shè)置cwnd為當(dāng)前ssthresh加上3倍的報文段大小。
代碼實現(xiàn)為:[java] view plaincopy step1:if ( dupacks >= 3 ) { ssthresh = max( 2 恍飘, cwnd / 2 ) 榨崩;cwnd = ssthresh + 3 * SMSS ;}
2)每次收到另一個重復(fù)的ACK時章母,cwnd++母蛛,并發(fā)送1個分組。注意H樵酢彩郊!是先按照上次cwnd發(fā)送數(shù)據(jù)包,然后再使cwnd增加一個報文段大小蚪缀。
3)當(dāng)下一個確認(rèn)新數(shù)據(jù)的ACK達到時秫逝,設(shè)置cwnd為ssthresh。這個ACK應(yīng)該是在進行重傳后的一個往返時間內(nèi)的所有中間報文段的確認(rèn)询枚。這一步采用的是擁塞避免违帆,因為當(dāng)分組丟失時我們將當(dāng)前的速率減半。
下圖是擁塞避免的一個例子:
我們注意當(dāng)cwnd為512時進行慢啟動金蜀,因為只有當(dāng)cwnd大于ssthresh才進行擁塞避免刷后,當(dāng)cwnd為768時此時進行的還是慢啟動的畴,注意因為cwnd的增加是進行發(fā)送數(shù)據(jù)包之后的時,代碼實現(xiàn)是:cwnd++即:進行完發(fā)包后才進行自加的尝胆!
當(dāng)一個通告窗口變化的ACK丟失后丧裁,則雙方就有可能因為等待對方而使連接終止:接收方等待接收數(shù)據(jù)(因為它已經(jīng)向發(fā)送方通告了一個非0的窗口),而發(fā)送方在等待允許它繼續(xù)發(fā)送數(shù)據(jù)的窗口更新班巩。為防止這種死鎖情況的發(fā)生渣慕,發(fā)送方使用一個堅持定時器(persist timer)來周期性地向接收方查詢,以便發(fā)現(xiàn)窗口是否增大抱慌。這些從發(fā)送發(fā)發(fā)出的報文段稱為窗口探查(window probe)逊桦。
同樣當(dāng)TCP一直收到窗口為0的ACK時,使用指數(shù)退避的方式發(fā)送堅持定時器抑进,TCP從不放棄發(fā)送窗口探查强经。這些探查每隔60s發(fā)送一次,這個過程將持續(xù)到或者窗口被打開寺渗,或者應(yīng)用程序使用的連接被終止匿情。
keepalive