3、連接建立的超時(shí)
有很多情況導(dǎo)致無法建立連接。一種情況是服務(wù)器主機(jī)沒有處于正常狀態(tài)。
4、最大報(bào)文段長(zhǎng)度
最大報(bào)文段長(zhǎng)度(MSS)表示TCP傳往另一端的最大塊數(shù)據(jù)的長(zhǎng)度。當(dāng)一個(gè)連接建立時(shí),連接的雙方都要通告各自的MSS。
當(dāng)建立一個(gè)連接時(shí),每一方都有用于通告它期望接收的MSS選項(xiàng)(MSS選項(xiàng)只能出現(xiàn)在SYN報(bào)文段中)。如果一方不接收來自另一方的MSS值,則MSS就定為默認(rèn)值536字節(jié)(這個(gè)默認(rèn)值允許20字節(jié)的IP首部和20字節(jié)的TCP首部以適合576字節(jié)IP數(shù)據(jù)報(bào))。
注意:
(1)一般說來,如果沒有分段發(fā)生,MSS越大越好。報(bào)文段越大允許每個(gè)報(bào)文段傳送的數(shù)據(jù)就越多,相對(duì)IP和TCP首部有更高的網(wǎng)絡(luò)利用率。
(2)當(dāng)TCP發(fā)送一個(gè)SYN時(shí),或者是因?yàn)橐粋€(gè)本地應(yīng)用進(jìn)程想發(fā)起一個(gè)連接,或者是因?yàn)榱硪欢说闹鳈C(jī)收到了一個(gè)連接請(qǐng)求,它能將MSS值設(shè)置為外出接口上的MTU長(zhǎng)度減去固定的IP首部和TCP首部長(zhǎng)度。
(3)如果目的IP地址為“非本地的(non-local)”,MSS通常的默認(rèn)值為536。
說明:區(qū)分地址是本地還是非本地的方法是:如果目的IP地址的網(wǎng)絡(luò)號(hào)與子網(wǎng)號(hào)都與本機(jī)相同,則是本地的;如果目的IP地址的網(wǎng)絡(luò)號(hào)與本機(jī)相同而子網(wǎng)號(hào)不同,則可能是本地的,也可能是非本地的。
(4)MSS使得主機(jī)限制另一端發(fā)送數(shù)據(jù)報(bào)的長(zhǎng)度。加上主機(jī)也能控制它發(fā)送數(shù)據(jù)報(bào)的長(zhǎng)度,這使得以較小MTU連接到一個(gè)網(wǎng)絡(luò)上的主機(jī)避免分段。
下面舉個(gè)書中的例子(比較懶,沒有搭建環(huán)境)
主機(jī)sun向slip發(fā)起一個(gè)TCP連接,利用tcpdump命令來觀察報(bào)文段:
說明:
(1)sun發(fā)送的報(bào)文段不能超過256字節(jié)的數(shù)據(jù),因?yàn)閟lip已經(jīng)告知它的MSS值為256。(上圖第二個(gè)紅框)
(2)slip知道它外出接口的MTU長(zhǎng)度為296,所以即使sun已經(jīng)告訴它的MSS為1460(上圖第一個(gè)紅框),但為避免將數(shù)據(jù)分段,它不會(huì)發(fā)送超過256字節(jié)數(shù)據(jù)的報(bào)文段。
(3)如果兩端主機(jī)都連接到以太網(wǎng)上,都采用536的MSS,但中間網(wǎng)絡(luò)采用296的MTU,同樣會(huì)出現(xiàn)分段。
5、TCP的半關(guān)閉
TCP提供了連接的一端在結(jié)束它的發(fā)送后還能接收來自另一端數(shù)據(jù)的能力,即半關(guān)閉。
注意:很少有應(yīng)用程序使用它,如果想要使用這個(gè)功能,需要編程接口提供一個(gè)方式來說明。
下面給出一個(gè)例子:
意思是這樣的:客戶結(jié)束了發(fā)送數(shù)據(jù)(發(fā)送了FIN),服務(wù)器發(fā)送ACK表示確認(rèn)后,仍然可以發(fā)送數(shù)據(jù)給客戶(圖中紅框)。
6、TCP的狀態(tài)變遷圖
下面這張圖我沒有仔細(xì)研究,它應(yīng)該包含了有關(guān)發(fā)起和終止TCP連接的所有規(guī)則。
(1)2MSL等待狀態(tài)
TIME_WAIT狀態(tài)也稱為2MSL等待狀態(tài)。每個(gè)具體TCP實(shí)現(xiàn)必須選擇一個(gè)報(bào)文段最大生存時(shí)間MSL(Maximum Segment Lifetime)。它是任何報(bào)文段被丟棄前在網(wǎng)絡(luò)內(nèi)的最長(zhǎng)時(shí)間。
注意:MSL是個(gè)有限的時(shí)間,我們知道TCP報(bào)文段以IP數(shù)據(jù)報(bào)在網(wǎng)絡(luò)中傳輸,IP數(shù)據(jù)報(bào)是由TTL字段限制其生存時(shí)間的。RFC 793指出MSL為2分鐘。實(shí)現(xiàn)中的常用值是30秒,1分鐘,或2分鐘。
對(duì)于給定的MSL值,原則是:當(dāng)TCP執(zhí)行一個(gè)主動(dòng)關(guān)閉,并發(fā)回最后一個(gè)ACK,該連接必須在TIME_WAIT狀態(tài)停留的時(shí)間為2倍的MSL。這樣可讓TCP再次發(fā)送最后的ACK以防這個(gè)ACK丟失(另一端超時(shí)并重發(fā)最后的FIN)。
說明:
1)客戶執(zhí)行主動(dòng)關(guān)閉并進(jìn)入TIME_WAIT是正常的。服務(wù)器通常執(zhí)行被動(dòng)關(guān)閉,不會(huì)進(jìn)入TIME_WAIT狀態(tài)。
2)TCP連接在2MSL等待期間,這個(gè)連接的socket(客戶的IP地址和端口號(hào),服務(wù)器的IP地址和端口號(hào))不能再被使用。這個(gè)連接只能在2MSL結(jié)束后才能再被使用。
(2)平靜時(shí)間的概念
如果處于2MSL等待端口的主機(jī)出現(xiàn)故障,它會(huì)在MSL秒內(nèi)重新啟動(dòng),并立即使用故障前處于2MSL的socket來建立一個(gè)新的連接。在故障前從這個(gè)連接發(fā)出而遲到的報(bào)文段會(huì)被錯(cuò)誤地當(dāng)作屬于重啟后新連接的報(bào)文段。
為了防止這種情況,RFC 793指出TCP在重啟動(dòng)后的MSL秒內(nèi)不能建立任何連接,稱為平靜時(shí)間(quiet time)。
(3)FIN_WAIT_2狀態(tài)
如上面的圖所示:FIN_WAIT_2狀態(tài)時(shí),客戶已經(jīng)發(fā)出了FIN,另一端也已對(duì)它進(jìn)行確認(rèn)。
除非客戶設(shè)置了半關(guān)閉,否則將等待另一端的應(yīng)用層意識(shí)到它已收到一個(gè)文件結(jié)束符說明,并向我們發(fā)一個(gè)FIN 來關(guān)閉連接。只有這樣,我們這端才會(huì)從FIN_WAIT_2狀態(tài)進(jìn)入TIME_WAIT狀態(tài)。
7、復(fù)位報(bào)文段
TCP首部中的RST比特是用于“復(fù)位”的,一般無論何時(shí)一個(gè)報(bào)文段發(fā)往“基準(zhǔn)連接”出現(xiàn)錯(cuò)誤,TCP都會(huì)發(fā)出一個(gè)復(fù)位報(bào)文段。
說明:“基準(zhǔn)連接”是指由目的IP地址和端口號(hào)以及源IP地址和端口號(hào)指明的連接。
(1)到不存在的端口的連接請(qǐng)求
產(chǎn)生復(fù)位的一種常見情況是當(dāng)連接請(qǐng)求到達(dá)時(shí),目的端口沒有進(jìn)程正在聽。
注意:對(duì)于UDP,當(dāng)一個(gè)數(shù)據(jù)報(bào)到達(dá)目的端口時(shí),該端口沒在使用,它將產(chǎn)生一個(gè)ICMP端口不可達(dá)的信息;對(duì)于TCP,則使用復(fù)位。
圖中的意思是說:主機(jī)bsdi向svr4的20000端口發(fā)送SYN,然后svr4告訴bsdi一個(gè)復(fù)位連接的信息。
(2)異常終止一個(gè)連接
終止一個(gè)連接的正常方式是一方發(fā)送FIN。這也稱為有序釋放,因?yàn)樵谒信抨?duì)數(shù)據(jù)都已發(fā)送之后才發(fā)送FIN,正常情況下沒有任何數(shù)據(jù)丟失。但也有可能發(fā)送一個(gè)復(fù)位報(bào)文段而不是FIN來中途釋放一個(gè)連接。這也稱為為異常釋放。
異常終止一個(gè)連接對(duì)應(yīng)用程序來說有兩個(gè)優(yōu)點(diǎn):
1)丟棄任何待發(fā)數(shù)據(jù)并立即發(fā)送復(fù)位報(bào)文段;
2)RST的接收方會(huì)區(qū)分另一端執(zhí)行的是異常關(guān)閉還是正常關(guān)閉。
特別注意:RST報(bào)文段不會(huì)導(dǎo)致另一端產(chǎn)生任何響應(yīng),另一端根本不進(jìn)行確認(rèn)。收到RST的一方將終止該連接,并通知應(yīng)用層連接復(fù)位。
(3)檢測(cè)半打開連接
如果一方已經(jīng)關(guān)閉或異常終止連接而另一方卻還不知道,將這樣的TCP連接稱為半打開的。
說明:
1)任何一端的主機(jī)異常都可能導(dǎo)致半打開連接。只要不在半打開連接上傳輸數(shù)據(jù),仍處于連接狀態(tài)的一方就不會(huì)檢測(cè)到另一方已經(jīng)出現(xiàn)異常。
2)半打開連接的另一個(gè)常見原因是當(dāng)客戶主機(jī)突然掉電而不是正常的結(jié)束客戶應(yīng)用程序后再關(guān)機(jī)。
8、同時(shí)打開
兩個(gè)應(yīng)用程序同時(shí)彼此執(zhí)行主動(dòng)打開的情況是可能的,盡管發(fā)生的可能性極小。每一方必須發(fā)送一個(gè)SYN,且這些SYN必須傳遞給對(duì)方。這需要每一方使用一個(gè)對(duì)方熟知的端口作為本地端口,稱為同時(shí)打開。
TCP對(duì)于同時(shí)打開僅建立一條連接而不是兩條連接。當(dāng)出現(xiàn)同時(shí)打開時(shí):
兩端幾乎同時(shí)發(fā)送SYN,并進(jìn)入SYN_SENT狀態(tài)。當(dāng)每一端收到SYN時(shí),狀態(tài)變?yōu)镾YN_RCVD,同時(shí)它們都再發(fā)SYN并對(duì)收到的SYN進(jìn)行確認(rèn)。當(dāng)雙方都收到SYN及相應(yīng)的ACK時(shí),狀態(tài)都變遷為ESTABLISHED。
注意:
(1)一個(gè)同時(shí)打開的連接需要交換4個(gè)報(bào)文段,比正常的三次握手多一個(gè)。
(2)對(duì)于同時(shí)打開的連接,我們沒有將任何一端稱為客戶或服務(wù)器,因?yàn)槊恳欢思仁强蛻粲质欠?wù)器。
9、同時(shí)關(guān)閉
雙方都執(zhí)行主動(dòng)關(guān)閉也是可能的,TCP也允許同時(shí)關(guān)閉。
同時(shí)關(guān)閉過程為:
(1)當(dāng)應(yīng)用層發(fā)出關(guān)閉命令時(shí),兩端均從ESTABLISHED變?yōu)镕IN_WAIT_1。這將導(dǎo)致雙方各發(fā)送一個(gè)FIN,兩個(gè)FIN經(jīng)過網(wǎng)絡(luò)傳送后分別到達(dá)另一端。
(2)收到FIN后,狀態(tài)由FIN_WAIT_1變?yōu)镃LOSING,并發(fā)送最后的ACK。
(3)當(dāng)收到最后的ACK時(shí),狀態(tài)變化為TIME_WAIT。
注意:同時(shí)關(guān)閉和正常關(guān)閉報(bào)文段交換數(shù)目相同。
10、TCP選項(xiàng)
TCP首部可以包含選項(xiàng)部分。
選項(xiàng)說明:
(1)每個(gè)選項(xiàng)的開始是1字節(jié)kind字段,說明選項(xiàng)的類型。
(2)kind字段為0和1的選項(xiàng)僅占1個(gè)字節(jié)。其他選項(xiàng)在kind字節(jié)后還有l(wèi)en字節(jié),它說明的長(zhǎng)度是指總長(zhǎng)度,包括kind字節(jié)和len字節(jié)。
(3)設(shè)置無操作選項(xiàng)的原因在于允許發(fā)方填充字段為4字節(jié)的倍數(shù)。
11、TCP 服務(wù)器的設(shè)計(jì)
大多數(shù)TCP服務(wù)器進(jìn)程是并發(fā)的。當(dāng)一個(gè)新的連接請(qǐng)求到達(dá)服務(wù)器時(shí),服務(wù)器接受這個(gè)請(qǐng)求,并調(diào)用一個(gè)新進(jìn)程來處理這個(gè)新的客戶請(qǐng)求。
(1)TCP服務(wù)器端口號(hào)
當(dāng)不同進(jìn)程連接到服務(wù)器時(shí),服務(wù)器端口號(hào)都是一樣的。
(2)限定的本地IP地址
限制本地的IP地址后,不同鏈路的連接請(qǐng)求可能被TCP內(nèi)核拒絕。
(3)限制遠(yuǎn)端IP地址
服務(wù)器必須不指明遠(yuǎn)端socket,而等待連接請(qǐng)求的到來,然后檢查客戶端的IP地址和端口號(hào)。
圖18-22(這張圖我還沒有看懂)總結(jié)了TCP服務(wù)器進(jìn)行連接時(shí)三種類型的地址綁定。在三種情況中,lport是服務(wù)器的熟知端口,local IP必須是一個(gè)本地接口的IP地址。
(4)呼入連接請(qǐng)求隊(duì)列
一個(gè)并發(fā)服務(wù)器調(diào)用一個(gè)新的進(jìn)程來處理每個(gè)客戶請(qǐng)求,因此處于被動(dòng)連接請(qǐng)求的服務(wù)器應(yīng)該始終準(zhǔn)備處理下一個(gè)呼入的連接請(qǐng)求。但仍有可能出現(xiàn)當(dāng)服務(wù)器在創(chuàng)建一個(gè)新的進(jìn)程時(shí),或操作系統(tǒng)正忙于處理優(yōu)先級(jí)更高的進(jìn)程時(shí),到達(dá)多個(gè)連接請(qǐng)求。
在伯克利的TCP實(shí)現(xiàn)中采用以下規(guī)則:
1)正等待連接請(qǐng)求的一端有一個(gè)固定長(zhǎng)度的連接隊(duì)列,該隊(duì)列中的連接已被TCP接受(即三次握手已經(jīng)完成),但還沒有被應(yīng)用層所接受。
注意:TCP接受一個(gè)連接是將其放入這個(gè)隊(duì)列,而應(yīng)用層接受連接是將其從該隊(duì)列中移出。
2)應(yīng)用層將指明該隊(duì)列的最大長(zhǎng)度,這個(gè)值通常稱為積壓值(backlog)。它的取值范圍是0~5之間的整數(shù),包括0和5(大多數(shù)的應(yīng)用程序都將這個(gè)值指明為5)。
3)當(dāng)一個(gè)連接請(qǐng)求(SYN)到達(dá)時(shí),TCP使用一個(gè)算法,根據(jù)當(dāng)前連接隊(duì)列中的連接數(shù)來確定是否接收這個(gè)連接。
4)如果對(duì)于新的連接請(qǐng)求,該TCP監(jiān)聽的端點(diǎn)的連接隊(duì)列中還有空間,TCP模塊將對(duì)SYN進(jìn)行確認(rèn)并完成連接的建立。
注意:
(i)應(yīng)用層只有在三次握手中的第三個(gè)報(bào)文段收到后才會(huì)知道這個(gè)新連接。
(ii)當(dāng)客戶進(jìn)程主動(dòng)打開成功但服務(wù)器的應(yīng)用層還不知道這個(gè)新的連接時(shí),它可能會(huì)認(rèn)為服務(wù)器進(jìn)程已經(jīng)準(zhǔn)備好接收數(shù)據(jù)了。如果這樣,服務(wù)器的TCP僅將接收的數(shù)據(jù)放入緩沖隊(duì)列。
5)如果對(duì)于新的連接請(qǐng)求,連接隊(duì)列中已沒有空間,TCP將不理會(huì)收到的SYN,也不發(fā)回任何報(bào)文段(即不發(fā)回RST)。如果應(yīng)用層不能及時(shí)接受已被TCP接受的連接,這些連接可能占滿整個(gè)連接隊(duì)列,客戶的主動(dòng)打開最終將超時(shí)。
聯(lián)系客服