《TCP/IP 詳解 卷1:協(xié)議》 第18章 TCP連接的建立與終止

??TCP是一個面向連接的協(xié)議平酿。無論哪一方向另一方發(fā)送數(shù)據(jù)之前尔艇,都必須現(xiàn)在雙方之間建立一條連接桨仿。

??連接的建立與終止

圖18-1 TCP連接建立與終止的tcpdump輸出顯示.png

??在第1行中,字段1415531521:1415531521(0)表示分組的序號是1415531521锡足,而報文段中數(shù)據(jù)字節(jié)數(shù)為0.
??tcpdump顯示這個字段的格式是開始的序號波丰、一個冒號、隱含的結尾序號及圓括號內(nèi)的數(shù)據(jù)字節(jié)數(shù)舶得。顯示序號和隱含結尾序號的優(yōu)點是便于了解數(shù)據(jù)字節(jié)數(shù)大于0時的隱含結尾序號掰烟。這個字段只有在滿足條件(1)報文段中至少包含一個數(shù)據(jù)字節(jié);或者(2)SYN沐批、FIN或RST被設置為1時才顯示纫骑。圖18-1中的第1、2九孩、4和6行是因為標志比特被置為1而顯示這個字段的先馆,在這個例子中通信雙方?jīng)]有交換任何數(shù)據(jù)。

??在第2行中躺彬,字段ack1415531522表示確認序號煤墙。它只有在首部中的ACK標志比特被設置1時才顯示梅惯。

??每行顯示的字段win4096表示發(fā)端通告的窗口大小。在這些例子中仿野,我們沒有交換任何數(shù)據(jù)铣减,窗口大小就維持默認情況下的4096(我們將在20.4節(jié)中討論TCP窗口大小)脚作。

??圖18-1中的最后一個字段<mss1024>表示由發(fā)端指明的最大報文段長度選項葫哗。發(fā)端將不接收超過這個長度的TCP報文段。這通常是為了避免分段球涛。

建立連接協(xié)議
image.png

??三次握手過程:

  • 1. 請求端(通常稱為客戶)發(fā)送一個SYN段指明客戶打算連接的服務器的端口劣针,以及初始序號(ISN,在這個例子中為1415531521)亿扁。這個SYN段為報文段1捺典。
  • 2. 服務器發(fā)回包含服務器的初始序號的SYN報文段(報文段2)作為應答。同時魏烫,將確認序號設置為客戶的ISN加1以對客戶的SYN報文段進行確認辣苏。一個SYN將占用一個序號。
  • 3. 客戶必須將確認序號設置為服務器的ISN加1以對服務器的SYN報文段進行確認(報文段3)哄褒。

??發(fā)送第一個SYN的一端將執(zhí)行主動打開(active open)。接收這個SYN并發(fā)回下一個SYN的另一端執(zhí)行被動打開(passive open)煌张。

??當一端為建立連接而發(fā)送它的SYN時呐赡,它為連接選擇一個初始序號。ISN隨時間而變化骏融,因此每個連接都將具有不同的ISN链嘀。

連接終止協(xié)議

??4次揮手過程:

??原因: 這由TCP的半關閉(halfclose)造成的。既然一個TCP連接是全雙工(即數(shù)據(jù)在兩個方向上能同時傳遞)档玻,因此每個方向必須單獨地進行關閉怀泊。這原則就是當一方完成它的數(shù)據(jù)發(fā)送任務后就能發(fā)送一個FIN來終止這個方向連接。當一端收到一個FIN误趴,它必須通知應用層另一端幾經(jīng)終止了那個方向的數(shù)據(jù)傳送霹琼。發(fā)送FIN通常是應用層進行關閉的結果。

??收到一個FIN只意味著在這一方向上沒有數(shù)據(jù)流動凉当。一個TCP連接在收到一個FIN后仍能發(fā)送數(shù)據(jù)枣申。而這對利用半關閉的應用來說是可能的,盡管在實際應用中只有很少的TCP應用程序這樣做看杭。

圖18-4 連接終止期間報文段的正常交換.png
  • 首先進行關閉的一方(即發(fā)送第一個FIN)將執(zhí)行關閉,而另一方(收到這個FIN)執(zhí)行被動關閉.通常一方完成主動關閉而另一方完成被動關閉

  • 當服務器收到這個FIN,它發(fā)回一個ACK,確認序號為收到的序號加1.和SYN一樣,一個FIN將占用一個序號.同時TCP服務器還向應用程序(即丟棄服務器)傳送一個文件結束符.接著這個服務程序就關閉它的連接,導致它的TCP端發(fā)送一個FIN,客戶端必須發(fā)回一個確認,并將確認序號設置為收到序號加1.

連接建立的超時

??有很多情況導致無法建立連接忠藤。一種情況是服務器主機沒有處于正常狀態(tài)。為了模擬這種情況楼雹,我們斷開服務器主機的電纜線模孩,然后向它發(fā)出telnet命令尖阔。圖18-6顯示了tcpdump的輸出。


圖18-6 建立連接超時的tcpdump輸出.png

??在這個輸出中有趣的一點是客戶間隔多長時間發(fā)送一個SYN榨咐,試圖建立連接介却。第2個SYN與第1個的間隔是5.8秒,而第3個與第2個的間隔是24秒祭芦。

最大報文端長度

??最大報文段長度(MSS)表示TCP傳往另一端的最大塊數(shù)據(jù)的長度.當一個連接建立時,連接的雙方都要通告各自的MSS.我們已經(jīng)見過MSS都是1024. 這導致IP數(shù)據(jù)報通常是40字節(jié):20字節(jié)的TCP首部和20字節(jié)的IP首部.

??當建立一個連接時,每一方都有用于通告它期望接受的MSS選項(MSS選項只能出現(xiàn)在SYN報文段中).如果一方不接受來自另一方的MSS值.則MSS就定位默認值536字節(jié)(這個默認值允許20字節(jié)的IP首部和20字節(jié)的TCP首部以適合576字節(jié)IP數(shù)據(jù)報)

TCP的半關閉

??半關閉: TCP提供了連接的一端在結束它的發(fā)送后還能接收來自另一端數(shù)據(jù)的能力筷笨。

圖18-10 TCP半關閉的例子.png

??為了使用這個特性,編程接口必須為應用程序提供一種方式來說明“我已經(jīng)完成了數(shù)據(jù)傳送龟劲,因此發(fā)送一個文件結束(FIN)給另一端胃夏,但我還想接收另一端發(fā)來的數(shù)據(jù),直到它給我發(fā)來文件結束(FIN)”昌跌。

??如果應用程序不調(diào)用close而調(diào)用shutdown仰禀,且第2個參數(shù)值為1,則插口的API支持半關閉蚕愤。然而答恶,大多數(shù)的應用程序通過調(diào)用close終止兩個方向的連接。

??圖18-10顯示了一個半關閉的典型例子萍诱。
讓左方的客戶端開始半關閉悬嗓,當然也可以由另一端開始。

  • 初始端發(fā)出的FIN裕坊,接著是另一端對這個FIN的ACK報文段

  • 接收半關閉的一方仍能發(fā)送數(shù)據(jù)包竹。我們只顯示一個數(shù)據(jù)報文段和一個ACK報文段,但可能發(fā)送了許多數(shù)據(jù)報文段

  • 當收到半關閉的一端在完成它的數(shù)據(jù)傳送后籍凝,將發(fā)送一個FIN關閉這個方向的連接周瞎,這將傳送一個文件結束符給發(fā)起這個半關閉的應用進程

  • 當對第二個FIN進行確認后,這個連接便徹底關閉了饵蒂。

為什么要有半關閉?
image.png

??沒有半關閉,需要其他的一些技術讓客戶通知服務器,客戶端已經(jīng)完成了它的數(shù)據(jù)傳送,但仍要接受來自服務端的數(shù)據(jù).使用兩個TCP連接也可作為一個選擇,但使用半關閉的單連接更好.

TCP的狀態(tài)變遷圖

圖18-12 TCP的狀態(tài)變遷圖.png
圖18-13 TCP正常連接建立和終止所對應的狀態(tài).png
2MSL等待狀態(tài)

??TIME_WAIT狀態(tài)也稱為2MSL等待狀態(tài)声诸。每個具體TCP實現(xiàn)必須選擇一個報文段最大生存時間MSL(Maximum Segment Lifetime)。它是任何報文段被丟棄前在網(wǎng)絡內(nèi)的最長時間退盯。我們知道這個時間是有限的彼乌,因為TCP報文段以IP數(shù)據(jù)報在網(wǎng)絡內(nèi)傳輸,而IP數(shù)據(jù)報則有限制其生存時間的TTL字段得问。

??對一個具體實現(xiàn)所給定的MSL值囤攀,處理的原則是:當TCP執(zhí)行一個主動關閉,并發(fā)回最后一個ACK宫纬,該連接必須在TIME_WAIT狀態(tài)停留的時間為2倍的MSL焚挠。這樣可讓TCP再次發(fā)送最后的ACK以防這個ACK丟失(另一端超時并重發(fā)最后的FIN)。

?這種2MSL等待的另一個結果是這個TCP連接在2MSL等待期間,定義這個連接的插口(客戶的IP地址和端口號,服務器的IP地址和端口)不能再被使用.這個連接只能在2MSL結束后才能再被使用.

??客戶執(zhí)行主動關閉并進入TIME_WAIT是正常的漓骚。服務器通常執(zhí)行被動關閉蝌衔,不會進入TIME_WAIT狀態(tài)榛泛。這暗示如果我們終止一個客戶程序,并立即重新啟動這個客戶程序噩斟,則這個新客戶程序將不能重用相同的本地端口曹锨。這不會帶來什么問題,因為客戶使用本地端口剃允,而并不關心這個端口號是什么沛简。

??然而,對于服務器斥废,情況就有所不同椒楣,因為服務器使用熟知端口。如果我們終止一個已經(jīng)建立連接的服務器程序牡肉,并試圖立即重新啟動這個服務器程序捧灰,服務器程序將不能把它的這個熟知端口賦值給它的端點,因為那個端口是處于2MSL連接的一部分统锤。在重新啟動服務器程序前毛俏,它需要在1~4分鐘.

FIN_WAIT_2狀態(tài)

??在FIN_WAIT_2狀態(tài)我們已經(jīng)發(fā)出了FIN,并且另一端也已對它進行確認饲窿。除非我們在實行半關閉煌寇,否則將等待另一端的應用層意識到它已收到一個文件結束符說明,并向我們發(fā)一個FIN來關閉另一方向的連接逾雄。只有當另一端的進程完成這個關閉唧席,我們這端才會從FIN_WAIT_2狀態(tài)進入TIME_WAIT狀態(tài)。

這意味著我們這端可能永遠保持這個狀態(tài)嘲驾。另一端也將處于CLOSE_WAIT狀態(tài),并一直保持這個狀態(tài)直到應用層決定進行關閉迹卢。

許多伯克利實現(xiàn)采用如下方式來防止這種在FIN_WAIT_2狀態(tài)的無限等待辽故。如果執(zhí)行主動關閉的應用層將進行全關閉,而不是半關閉來說明它還想接收數(shù)據(jù)腐碱,就設置一個定時器誊垢。如果這個連接空閑10分鐘75秒,TCP將進入CLOSED狀態(tài)症见。在實現(xiàn)代碼的注釋中確認這個實現(xiàn)代碼違背協(xié)議的規(guī)范喂走。

復位報文段

??TCP首部中的RST比特是用于"復位"的.一般說來,無論何時一個報文段發(fā)往基準的連接出現(xiàn)錯誤,TCP都會出現(xiàn)一個復位報文段.

出現(xiàn)情況:

  • 到不存在的端口的連接請求
    ?產(chǎn)生復位的一種常見情況是當連接請求到達時,目的端口沒有進程正在聽.當一個數(shù)據(jù)報到達目的端口時,該端口沒在使用,TCP使用復位


    image.png
  • 異常終止一個連接
    ?終止一個連接的正常方式是一方發(fā)送FIN.有時這也稱為有序釋放(orderly release),因為在所有排隊數(shù)據(jù)都已發(fā)送之后才發(fā)送FIN,正常情況下沒有任何數(shù)據(jù)丟失.但也有可能發(fā)送一個復位報文段而不是FIN來中途釋放一個連接.這被稱為異常釋放
    ?異常終止一個連接對應用程序來說有兩個優(yōu)點:(1)丟棄任何待發(fā)數(shù)據(jù)并立即發(fā)送復位報文段;(2)RST的接收方會區(qū)分另一端執(zhí)行的是異常關閉還是正常關閉.應用程序使用的API必須提供產(chǎn)生異常關閉而不是正常關閉的手段.
半打開連接

?如果一方已經(jīng)關閉或異常終止連接而另一方卻還不知道,我們將這樣的TCP連接稱為半打開(Half-Open)的.任何一端的主機異常都可能導致發(fā)送這種情況.只要不打算在半打開連接上傳輸數(shù)據(jù)谋作,仍處于連接狀態(tài)的一方就不會檢測另一方已經(jīng)出現(xiàn)異常芋肠。

?半打開連接的另一個常見原因是當客戶主機突然掉電而不是正常的結束客戶應用程序后再關機。這可能發(fā)生在使用PC機作為Telnet的客戶主機上遵蚜,例如帖池,用戶在一天工作結束時關閉PC機的電源奈惑。當關閉PC機電源時,如果已不再有要向服務器發(fā)送的數(shù)據(jù)睡汹,服務器將永遠不知道客戶程序已經(jīng)消失了肴甸。當用戶在第二天到來時,打開PC機囚巴,并啟動新的Telnet客戶程序原在,在服務器主機上會啟動一個新的服務器程序。這樣會導致服務器主機中產(chǎn)生許多半打開的TCP連接

同時打開
image.png

??TCP特意設計可以處理同時打開,對于同時打開它僅建立一條連接而不是兩條連接;
??一個同時打開的連接需要交換4個報文段,比正常的三次握手多一個.此外,我們沒有將任何一端稱為客戶或服務器,因為每一端既是客戶又是服務器.

同時關閉
image.png

??當應用層發(fā)出關閉命令時彤叉,兩端均從ESTABLISHED變?yōu)镕IN_WAIT_1庶柿。這將導致雙方各發(fā)送一個FIN,兩個FIN經(jīng)過網(wǎng)絡傳送后分別到達另一端姆坚。收到FIN后澳泵,狀態(tài)由FIN_WAIT_1變遷到CLOSING,并發(fā)送最后的ACK兼呵。當收到最后的ACK時兔辅,狀態(tài)變化為TIME_WAIT。
??同時關閉與正常關閉使用的段交換數(shù)目相同击喂。

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末维苔,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子懂昂,更是在濱河造成了極大的恐慌介时,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件凌彬,死亡現(xiàn)場離奇詭異沸柔,居然都是意外死亡,警方通過查閱死者的電腦和手機铲敛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評論 3 385
  • 文/潘曉璐 我一進店門褐澎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人伐蒋,你說我怎么就攤上這事工三。” “怎么了先鱼?”我有些...
    開封第一講書人閱讀 158,369評論 0 348
  • 文/不壞的土叔 我叫張陵俭正,是天一觀的道長。 經(jīng)常有香客問我焙畔,道長掸读,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,799評論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮寺枉,結果婚禮上抑淫,老公的妹妹穿的比我還像新娘。我一直安慰自己姥闪,他們只是感情好始苇,可當我...
    茶點故事閱讀 65,910評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著筐喳,像睡著了一般催式。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上避归,一...
    開封第一講書人閱讀 50,096評論 1 291
  • 那天荣月,我揣著相機與錄音,去河邊找鬼梳毙。 笑死哺窄,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的账锹。 我是一名探鬼主播萌业,決...
    沈念sama閱讀 39,159評論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼奸柬!你這毒婦竟也來了生年?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,917評論 0 268
  • 序言:老撾萬榮一對情侶失蹤廓奕,失蹤者是張志新(化名)和其女友劉穎抱婉,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體桌粉,經(jīng)...
    沈念sama閱讀 44,360評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡蒸绩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,673評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了铃肯。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片侵贵。...
    茶點故事閱讀 38,814評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖缘薛,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情卡睦,我是刑警寧澤宴胧,帶...
    沈念sama閱讀 34,509評論 4 334
  • 正文 年R本政府宣布,位于F島的核電站表锻,受9級特大地震影響恕齐,放射性物質發(fā)生泄漏。R本人自食惡果不足惜瞬逊,卻給世界環(huán)境...
    茶點故事閱讀 40,156評論 3 317
  • 文/蒙蒙 一显歧、第九天 我趴在偏房一處隱蔽的房頂上張望仪或。 院中可真熱鬧,春花似錦士骤、人聲如沸范删。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽到旦。三九已至,卻和暖如春巨缘,著一層夾襖步出監(jiān)牢的瞬間添忘,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評論 1 267
  • 我被黑心中介騙來泰國打工若锁, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留搁骑,地道東北人。 一個月前我還...
    沈念sama閱讀 46,641評論 2 362
  • 正文 我出身青樓又固,卻偏偏與公主長得像仲器,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子口予,可洞房花燭夜當晚...
    茶點故事閱讀 43,728評論 2 351

推薦閱讀更多精彩內(nèi)容