??建立TCP的連接昌讲,就得先說(shuō)說(shuō)TCP的報(bào)文首部酗捌。TCP的全部功能都體現(xiàn)在它首部的各個(gè)字段的作用妈橄。下面說(shuō)明TCP首部格式。
??TCP報(bào)文段的前20個(gè)字節(jié)是固定的赞庶,后面有4n個(gè)字節(jié)是根據(jù)需要而增加的選項(xiàng)(n是整數(shù))训挡。因此TCP首部的最小長(zhǎng)度是20個(gè)字節(jié)。
TCP報(bào)文首部
??首部固定部分各字段的意義如下:
????(1)源端口和目的端口????各占2個(gè)字節(jié)歧强,分別寫(xiě)入 源端口號(hào)和目的端口號(hào)澜薄。
????(2)序號(hào)????占4字節(jié)。序號(hào)范圍是[0,2^32 -1],共232個(gè)序號(hào)摊册。序號(hào)增加到232 -1后肤京,下一個(gè)序號(hào)就又回到0。
??????例如:一報(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)文段(如果還有的話)的數(shù)據(jù)序號(hào)應(yīng)當(dāng)從401開(kāi)始。
????(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卤恳,而數(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若债,于是B在發(fā)送給A的確認(rèn)報(bào)文段中把確認(rèn)號(hào)置為701。
??????總之拆融,應(yīng)當(dāng)記状懒铡:
若確認(rèn)號(hào)=N,則表明:到序號(hào)N-1為止的所有數(shù)據(jù)都已正確收到。
????(4)數(shù)據(jù)偏移????占4位镜豹,是TCP報(bào)文段的首部長(zhǎng)度傲须。
????(5)保留????占6位,保留為今后使用趟脂,但目前應(yīng)置為0泰讽。
????(6)緊急URG ????當(dāng)URG=1時(shí),表明緊急指針字段有效昔期。
????(7)確認(rèn)ACK ????僅當(dāng)ACK=1時(shí)確認(rèn)號(hào)字段才有效已卸。當(dāng)ACK=0時(shí),確認(rèn)號(hào)無(wú)效硼一。TCP規(guī)定累澡,在連接建立后所有傳送的報(bào)文段都必須把ACK置1。
????(8)推送PSH ????當(dāng)兩個(gè)應(yīng)用進(jìn)程進(jìn)行交互式通信時(shí)般贼,有時(shí)在一端的應(yīng)用進(jìn)程希望在鍵入一個(gè)命令后立即就能收到對(duì)方的響應(yīng)愧哟,這時(shí)候就將PSH=1。
????(9)復(fù)位RST ????當(dāng)RST=1哼蛆,表明TCP連接中出現(xiàn)嚴(yán)重差錯(cuò)蕊梧,必須釋放連接,然后再重新建立連接人芽。
????(10)同步SYN ????在連接建立時(shí)用來(lái)同步序號(hào)望几。當(dāng)SYN=1,ACK=0萤厅,表明是連接請(qǐng)求報(bào)文橄抹,若同意連接,則響應(yīng)報(bào)文中應(yīng)該使SYN=1惕味,ACK=1楼誓。
????(11)終止FIN ????用來(lái)釋放一個(gè)連接。當(dāng)FIN=1名挥,表明此報(bào)文的發(fā)送方的數(shù)據(jù)已經(jīng)發(fā)送完畢疟羹,并且要求釋放。
????(12)窗口 ????占2字節(jié)。是接收方告訴發(fā)送方我還可以容納窗口大小的數(shù)據(jù)榄融。
??????例如:發(fā)送一個(gè)報(bào)文段参淫,其確認(rèn)號(hào)是701,窗口大小是1000愧杯。這就告訴對(duì)方:“從701號(hào)算起涎才,我的接收緩存還可以接收1000個(gè)字節(jié)數(shù)據(jù),你發(fā)送數(shù)據(jù)時(shí)力九,必須要考慮到這一點(diǎn)”耍铜。
????(13)校驗(yàn)和 ????占2字節(jié)。校驗(yàn)首部和數(shù)據(jù)這兩部分跌前。
????(14)緊急指針 ????占2字節(jié)棕兼。指出本報(bào)文段中的緊急數(shù)據(jù)的字節(jié)數(shù)。
????(15)選項(xiàng) ????長(zhǎng)度可變抵乓,定義一些其他的可選的參數(shù)伴挚。當(dāng)沒(méi)有使用“選項(xiàng)”時(shí),TCP的首部長(zhǎng)度是20個(gè)字節(jié)臂寝。
TCP的連接建立
??假定主機(jī)A運(yùn)行的是TCP客戶程序章鲤,而B(niǎo)運(yùn)行TCP服務(wù)器程序。最初兩端的TCP進(jìn)程都處于CLOSED(關(guān)閉)狀態(tài)咆贬“芑玻客戶端A主動(dòng)打開(kāi),而B(niǎo)被動(dòng)打開(kāi)掏缎。
??1)服務(wù)器B先創(chuàng)建傳輸控制塊TCB皱蹦,準(zhǔn)備接受客戶的連接請(qǐng)求。然后服務(wù)器就處于LISTEN(收聽(tīng))狀態(tài)眷蜈,等待客戶的連接請(qǐng)求沪哺。如有,即作出相應(yīng)酌儒。
??2)客戶端A也首先創(chuàng)建傳輸控制模塊TCB辜妓。然后,向B發(fā)出連接請(qǐng)求報(bào)文段忌怎,這時(shí)報(bào)文首部中的同步位SYN=1籍滴,同時(shí)選擇一個(gè)初始序列號(hào) seq=x 曼玩。TCP客戶端進(jìn)程進(jìn)入了 SYN-SENT(同步已發(fā)送狀態(tài))狀態(tài)溉潭。TCP規(guī)定骂蓖,SYN報(bào)文段(SYN=1的報(bào)文段)不能攜帶數(shù)據(jù)峦剔,但需要消耗掉一個(gè)序號(hào)。
??3)B收到請(qǐng)求報(bào)文后震束,如同意建立連接递鹉,則向A發(fā)出確認(rèn)上煤。在確認(rèn)報(bào)文中應(yīng)該把 ACK位和SYN位都置1,確認(rèn)號(hào)是ack=x+1狂鞋,同時(shí)也要為自己選擇一個(gè)序列號(hào) seq=y片择,此時(shí),TCP服務(wù)器進(jìn)程進(jìn)入了SYN-RCVD(同步收到)狀態(tài)要销。注意构回,這個(gè)報(bào)文也不能攜帶數(shù)據(jù)夏块,但是同樣要消耗一個(gè)序號(hào)疏咐。
??4)TCP客戶進(jìn)程收到B的確認(rèn)后,還要向B給出確認(rèn)脐供。確認(rèn)報(bào)文的ACK=1浑塞,ack=y+1,自己的序列號(hào)seq=x+1政己。此時(shí)酌壕,TCP連接已經(jīng)建立,客戶端進(jìn)入ESTABLISHED(已建立連接)狀態(tài)歇由。TCP規(guī)定卵牍,ACK報(bào)文段可以攜帶數(shù)據(jù),但是如果不攜帶數(shù)據(jù)則不消耗序號(hào)沦泌。
??5)當(dāng)B收到A的確認(rèn)后糊昙,也進(jìn)入ESTABLISHED狀態(tài)。
為什么A最后還要發(fā)送一次確認(rèn)呢谢谦?
這主要是為了防止已失效的連接請(qǐng)求報(bào)文段突然又傳送到B释牺,因而產(chǎn)生錯(cuò)誤。
所謂“已失效的連接請(qǐng)求報(bào)文段”是這樣產(chǎn)生的回挽。假設(shè)有這樣一種場(chǎng)景没咙,客戶端發(fā)送了第一個(gè)請(qǐng)求連接并且沒(méi)
有丟失,只是因?yàn)樵诰W(wǎng)絡(luò)結(jié)點(diǎn)中滯留的時(shí)間太長(zhǎng)了千劈,由于TCP的客戶端遲遲沒(méi)有收到確認(rèn)報(bào)文祭刚,以為服務(wù)器
沒(méi)有收到,此時(shí)重新向服務(wù)器發(fā)送請(qǐng)求報(bào)文墙牌,此后客戶端和服務(wù)器建立連接涡驮,傳輸數(shù)據(jù),然后關(guān)閉連接憔古。
此時(shí)之前滯留的那一次請(qǐng)求連接遮怜,網(wǎng)絡(luò)通暢了到達(dá)了服務(wù)器,這個(gè)請(qǐng)求報(bào)文本該是失效的鸿市,但是锯梁,服務(wù)器
收到此失效請(qǐng)求報(bào)文即碗,就誤以為是客戶端又發(fā)出一次新的連接請(qǐng)求。于是就向客戶端發(fā)出確認(rèn)報(bào)文陌凳,同意
建立連接剥懒。假定不采用報(bào)文握手,那么只要服務(wù)器發(fā)出確認(rèn)合敦,新的連接就建立了初橘。
由于客戶端沒(méi)有發(fā)出建立連接請(qǐng)求,因此不會(huì)理睬服務(wù)器的確認(rèn)充岛,也不會(huì)向服務(wù)器發(fā)數(shù)據(jù)保檐,但服務(wù)器卻以
為連接已經(jīng)建立了,等待客戶端發(fā)數(shù)據(jù)崔梗,服務(wù)器的許多資源就這樣白白浪費(fèi)了夜只。
TCP的連接釋放
A和B都處于ESTABLISHED狀態(tài),然后客戶端主動(dòng)關(guān)閉蒜魄,服務(wù)器被動(dòng)關(guān)閉扔亥。
??1)A的應(yīng)用進(jìn)程先向其TCP發(fā)出連接釋放報(bào)文,并停止發(fā)送數(shù)據(jù)谈为,主動(dòng)關(guān)閉TCP連接旅挤。A把連接釋放的報(bào)文段首部的終止控制位FIN置1,其序列號(hào)為seq=u(等于前面已經(jīng)傳送過(guò)來(lái)的數(shù)據(jù)的最后一個(gè)字節(jié)的序號(hào)加1)伞鲫。此時(shí)粘茄,A進(jìn)入FIN-WAIT-1(終止等待1)狀態(tài),等待B的確認(rèn)。注意榔昔, TCP規(guī)定驹闰,FIN報(bào)文段即使不攜帶數(shù)據(jù),也要消耗一個(gè)序號(hào)撒会。
??2)B收到連接釋放報(bào)文后發(fā)出確認(rèn)嘹朗,ACK=1,ack=u+1诵肛,并且?guī)献约旱男蛄刑?hào)seq=v屹培。此時(shí),B就進(jìn)入了CLOSE-WAIT(關(guān)閉等待)狀態(tài)怔檩。TCP服務(wù)器通知高層的應(yīng)用進(jìn)程褪秀,客戶端向服務(wù)器的方向就釋放了,這時(shí)候處于半關(guān)閉狀態(tài)薛训,即客戶端已經(jīng)沒(méi)有數(shù)據(jù)要發(fā)送了媒吗,但是服務(wù)器若發(fā)送數(shù)據(jù),客戶端依然要接受乙埃。這個(gè)狀態(tài)可能要持續(xù)一段時(shí)間闸英,也就是整個(gè)CLOSE-WAIT狀態(tài)持續(xù)的時(shí)間锯岖。
??3)A收到B的確認(rèn)后,就進(jìn)入FIN-WAIT-2(終止等待2)狀態(tài)甫何,等待B發(fā)出連接釋放報(bào)文(在這之前還需要接受服務(wù)器發(fā)送的最后的數(shù)據(jù))出吹。
??4)若B已經(jīng)沒(méi)有要向A發(fā)送的數(shù)據(jù),其應(yīng)用進(jìn)程就通知TCP釋放連接辙喂。這時(shí)B發(fā)出的連接釋放報(bào)文段必須使用FIN=1捶牢,ack=u+1,由于在半關(guān)閉狀態(tài)巍耗,B很可能又發(fā)送了一些數(shù)據(jù)秋麸,假定此時(shí)的序列號(hào)為seq=w,此時(shí),B就進(jìn)入了LAST-ACK(最后確認(rèn))狀態(tài)芍锦,等待A的確認(rèn)竹勉。
??5)A收到B的連接釋放報(bào)文段后,必須對(duì)此發(fā)出確認(rèn)娄琉,在確認(rèn)報(bào)文段中將ACK=1,ack=w+1吓歇,而自己的序列號(hào)是seq=u+1孽水。此時(shí),A就進(jìn)入了TIME-WAIT(時(shí)間等待)狀態(tài)城看。注意此時(shí)TCP連接還沒(méi)有釋放女气,必須經(jīng)過(guò)2MSL(最長(zhǎng)報(bào)文段壽命,建議設(shè)為2分鐘,對(duì)于現(xiàn)在的網(wǎng)絡(luò)测柠,MSL=2分鐘可能長(zhǎng)了些)的時(shí)間后炼鞠,當(dāng)客戶端撤銷相應(yīng)的TCB后,才進(jìn)入CLOSED狀態(tài)轰胁。
??6)B只要收到了A發(fā)出的確認(rèn)谒主,立即進(jìn)入CLOSED狀態(tài)。同樣赃阀,撤銷TCB后霎肯,就結(jié)束了這次的TCP連接¢凰梗可以看到观游,服務(wù)器結(jié)束TCP連接的時(shí)間要比客戶端早一些。
為什么A在TIME-WAIT狀態(tài)必須等待2MSL的時(shí)間呢驮俗?
????1)為了保證A發(fā)送的最后一個(gè)ACK報(bào)文段能夠到達(dá)B懂缕。這個(gè)ACK報(bào)文段可能會(huì)丟失,因而使處在LAST-ACK(最后確認(rèn)狀態(tài))的B收不到對(duì)已發(fā)送的FIN+ACK報(bào)文段的確認(rèn)王凑。B會(huì)超時(shí)重傳這個(gè)FIN+ACK報(bào)文段搪柑,而A在2MSL時(shí)間內(nèi)就能收到這個(gè)重傳的報(bào)文段吮蛹,最后,A和B就能正常釋放連接拌屏。
????2)防止“已失效的連接請(qǐng)求報(bào)文段”出現(xiàn)在本連接中潮针。A在發(fā)送完最后一個(gè)ACK報(bào)文段后,再經(jīng)過(guò)2MSL時(shí)間倚喂,就可以使本連接持續(xù)的時(shí)間內(nèi)產(chǎn)生的所有報(bào)文段都從網(wǎng)絡(luò)中消失每篷。
連接建立后,A突然出現(xiàn)故障端圈,此時(shí)應(yīng)該怎么辦焦读?
??除了時(shí)間等待計(jì)時(shí)器外,TCP還有一個(gè)辈杖ǎ活計(jì)時(shí)器矗晃。當(dāng)B每收到一次A發(fā)送來(lái)得數(shù)據(jù)時(shí),就重新設(shè)置毖绫叮活計(jì)時(shí)器张症,時(shí)間的設(shè)置通常是兩個(gè)小時(shí)。若兩個(gè)小時(shí)沒(méi)有收到A的數(shù)據(jù)鸵贬,B就發(fā)送一個(gè)探測(cè)報(bào)文段俗他,以后每隔75秒發(fā)送一次。若一連發(fā)送10個(gè)探測(cè)報(bào)文段后扔沒(méi)有收到A的響應(yīng)阔逼,B就認(rèn)為A出現(xiàn)故障兆衅,接著就關(guān)閉連接。