為什么 TCP 建立連接需要三次握手 · Why's THE Design?

為什么這么設(shè)計(Why's THE Design)是一系列關(guān)于計算機(jī)領(lǐng)域中程序設(shè)計決策的文章暖夭,我們在這個系列的每一篇文章中都會提出一個具體的問題并從不同的角度討論這種設(shè)計的優(yōu)缺點(diǎn)回还、對具體實(shí)現(xiàn)造成的影響厕氨。如果你有想要了解的問題驻售,可以在文章下面留言狸涌。
原文鏈接 https://draveness.me/whys-the-design-tcp-three-way-handshake

TCP 協(xié)議是我們幾乎每天都會接觸到的網(wǎng)絡(luò)協(xié)議果港,絕大多數(shù)網(wǎng)絡(luò)連接的建立都是基于 TCP 協(xié)議的廉羔,學(xué)過計算機(jī)網(wǎng)絡(luò)或者對 TCP 協(xié)議稍有了解的人都知道 —— 使用 TCP 協(xié)議建立連接需要經(jīng)過三次握手(three-way handshake)。

如果讓我們簡單說說 TCP 建立連接的過程塘揣,相信很多準(zhǔn)備過面試的人都會非常了解包雀,但是一旦想要深究『為什么 TCP 建立連接需要三次握手?』亲铡,作者相信大多數(shù)人都沒有辦法回答這個問題或者會給出錯誤的答案才写,這邊文章就會討論究竟為什么我們需要三次握手才能建立 TCP 連接?

需要注意的是我們會將重點(diǎn)放到為什么需要 TCP 建立連接需要『三次握手』奖蔓,而不僅僅是為什么需要『三次』握手琅摩。

概述

在具體分析今天的問題之前,我們首先可以了解一下最常見的錯誤類比锭硼,這個對 TCP 連接過程的錯誤比喻誤導(dǎo)了很多人,作者在比較長的一段時間內(nèi)也認(rèn)為它能夠很好地描述 TCP 建立連接為什么需要三次握手:

  1. 你聽得到嗎蜕劝?
  2. 我能聽到檀头,你聽得到轰异?
  3. 我也能聽到;

這種用類比來解釋問題往往就會面臨『十個類比九個錯』的尷尬局面暑始,如果別人用類比回答你的為什么搭独,你需要仔細(xì)想一想它的類比里究竟哪里有漏洞;類比帶來的解釋往往只能有片面的相似性廊镜,我們永遠(yuǎn)也無法找到絕對正確的類比牙肝,它只在我們想要通俗易懂地展示事物的特性時才能發(fā)揮較大的作用,我們在文章的后面會介紹為什么這里的類比有問題嗤朴,各位讀者也可以帶著疑問來閱讀剩下的內(nèi)容配椭。

很多人嘗試回答或者思考這個問題的時候其實(shí)關(guān)注點(diǎn)都放在了三次握手中的三次上面,這確實(shí)很重要雹姊,但是如果重新審視這個問題股缸,我們對于『什么是連接』真的清楚?只有知道連接的定義吱雏,我們才能去嘗試回答為什么 TCP 建立連接需要三次握手敦姻。

The reliability and flow control mechanisms described above require that TCPs initialize and maintain certain status information for each data stream. The combination of this information, including sockets, sequence numbers, and window sizes, is called a connection.

RFC 793 - Transmission Control Protocol 文檔中非常清楚地定義了 TCP 中的連接是什么,我們簡單總結(jié)一下:用于保證可靠性和流控制機(jī)制的信息歧杏,包括 Socket镰惦、序列號以及窗口大小叫做連接。

what-is-tcp-connection

所以犬绒,建立 TCP 連接就是通信的雙方需要對上述的三種信息達(dá)成共識旺入,連接中的一對 Socket 是由互聯(lián)網(wǎng)地址標(biāo)志符和端口組成的,窗口大小主要用來做流控制懂更,最后的序列號是用來追蹤通信發(fā)起方發(fā)送的數(shù)據(jù)包序號眨业,接收方可以通過序列號向發(fā)送方確認(rèn)某個數(shù)據(jù)包的成功接收。

到這里沮协,我們將原有的問題轉(zhuǎn)換成了『為什么需要通過三次握手才可以初始化 Sockets龄捡、窗口大小和初始序列號?』慷暂,那么接下來我們就開始對這個細(xì)化的問題進(jìn)行分析并尋找解釋聘殖。

設(shè)計

這篇文章主要會從以下幾個方面介紹為什么我們需要通過三次握手才可以初始化 Sockets、窗口大小行瑞、初始序列號并建立 TCP 連接:

  • 通過三次握手才能阻止重復(fù)歷史連接的初始化奸腺;
  • 通過三次握手才能對通信雙方的初始序列號進(jìn)行初始化;
  • 討論其他次數(shù)握手建立連接的可能性血久;

這幾個論點(diǎn)中的第一個是 TCP 選擇使用三次握手的最主要原因突照,其他的幾個原因相比之下都是次要的原因,我們在這里對它們的討論只是為了讓整個視角更加豐富氧吐,通過多方面理解這一有趣的設(shè)計決策讹蘑。

歷史連接

RFC 793 - Transmission Control Protocol 其實(shí)就指出了 TCP 連接使用三次握手的首要原因 —— 為了阻止歷史的重復(fù)連接初始化造成的混亂問題末盔,防止使用 TCP 協(xié)議通信的雙方建立了錯誤的連接。

The principle reason for the three-way handshake is to prevent old duplicate connection initiations from causing confusion.

tcp-recovery-from-old-duplicate-syn

想象一下這個場景座慰,如果通信雙方的通信次數(shù)只有兩次陨舱,那么發(fā)送方一旦發(fā)出建立連接的請求之后它就沒有辦法撤回這一次請求,如果在網(wǎng)絡(luò)狀況復(fù)雜或者較差的網(wǎng)絡(luò)中版仔,發(fā)送方連續(xù)發(fā)送多次建立連接的請求游盲,如果 TCP 建立連接只能通信兩次,那么接收方只能選擇接受或者拒絕發(fā)送方發(fā)起的請求蛮粮,它并不清楚這一次請求是不是由于網(wǎng)絡(luò)擁堵而早早過期的連接益缎。

所以,TCP 選擇使用三次握手來建立連接并在連接引入了 RST 這一控制消息蝉揍,接收方當(dāng)收到請求時會將發(fā)送方發(fā)來的 SEQ+1 發(fā)送回接收方链峭,這時由發(fā)送方來判斷當(dāng)前連接是否是歷史連接:

  • 如果當(dāng)前連接是歷史連接,即 SEQ 過期或者超時又沾,那么發(fā)送方就會直接發(fā)送 RST 控制消息中止這一次連接弊仪;
  • 如果當(dāng)前連接不是歷史連接,那么發(fā)送方就會發(fā)送 ACK 控制消息杖刷,通信雙方就會成功建立連接励饵;

使用三次握手和 RST 控制消息將是否建立連接的最終控制權(quán)交給了發(fā)送方,因?yàn)橹挥邪l(fā)送方有足夠的上下文來判斷當(dāng)前連接是否是錯誤的或者過期的滑燃,這也是 TCP 使用三次握手建立連接的最主要原因役听。

初始序列號

另一個使用三次握手的重要的原因就是通信雙方都需要獲得一個用于發(fā)送信息的初始化序列號,作為一個可靠的傳輸層協(xié)議表窘,TCP 需要在不穩(wěn)定的網(wǎng)絡(luò)環(huán)境中構(gòu)建一個可靠的傳輸層典予,網(wǎng)絡(luò)的不確定性可能會導(dǎo)致數(shù)據(jù)包的缺失和順序顛倒等問題,常見的問題可能包括:

  • 數(shù)據(jù)包被發(fā)送方多次發(fā)送造成數(shù)據(jù)的重復(fù)乐严;
  • 數(shù)據(jù)包在傳輸?shù)倪^程中被路由或者其他節(jié)點(diǎn)丟失瘤袖;
  • 數(shù)據(jù)包到達(dá)接收方可能無法按照發(fā)送順序;

為了解決上述這些可能存在的問題昂验,TCP 協(xié)議要求發(fā)送方在數(shù)據(jù)包中加入『序列號』字段捂敌,有了數(shù)據(jù)包對應(yīng)的序列號,我們就可以:

  • 接收方可以通過序列號對重復(fù)的數(shù)據(jù)包進(jìn)行去重既琴;
  • 發(fā)送方會在對應(yīng)數(shù)據(jù)包未被 ACK 時進(jìn)行重復(fù)發(fā)送占婉;
  • 接收方可以根據(jù)數(shù)據(jù)包的序列號對它們進(jìn)行重新排序;

序列號在 TCP 連接中有著非常重要的作用甫恩,初始序列號作為 TCP 連接的一部分也需要在三次握手期間進(jìn)行初始化逆济,由于 TCP 連接通信的雙方都需要獲得初始序列號,所以它們其實(shí)需要向?qū)Ψ桨l(fā)送 SYN 控制消息并攜帶自己期望的初始化序列號 SEQ,對方在收到 SYN 消息之后會通過 ACK 控制消息以及 SEQ+1 來進(jìn)行確認(rèn)奖慌。

basic-4-way-handshake

如上圖所示霎终,通信雙方的兩個 TCP A/B 分別向?qū)Ψ桨l(fā)送 SYNACK 控制消息,等待通信雙方都獲取到了自己期望的初始化序列號之后就可以開始通信了升薯,由于 TCP 消息頭的設(shè)計,我們可以將中間的兩次通信合成一個击困,TCP B 可以向 TCP A 同時發(fā)送 ACKSYN 控制消息涎劈,這也就幫助我們將四次通信減少至三次。

A three way handshake is necessary because sequence numbers are not tied to a global clock in the network, and TCPs may have different mechanisms for picking the ISN's. The receiver of the first SYN has no way of knowing whether the segment was an old delayed one or not, unless it remembers the last sequence number used on the connection (which is not always possible), and so it must ask the sender to verify this SYN. The three way handshake and the advantages of a clock-driven scheme are discussed in [3].

除此之外阅茶,網(wǎng)絡(luò)作為一個分布式的系統(tǒng)蛛枚,其中并不存在一個用于計數(shù)的全局時鐘,而 TCP 可以通過不同的機(jī)制來初始化序列號脸哀,作為 TCP 連接的接收方我們無法判斷對方傳來的初始化序列號是否過期蹦浦,所以我們需要交由對方來判斷,TCP 連接的發(fā)起方可以通過保存發(fā)出的序列號判斷連接是否過期撞蜂,如果讓接收方來保存并判斷序列號卻是不現(xiàn)實(shí)的盲镶,這也再一次強(qiáng)化了我們在上一節(jié)中提出的觀點(diǎn) —— 避免歷史錯連接的初始化。

通信次數(shù)

當(dāng)我們討論 TCP 建立連接需要的通信次數(shù)時蝌诡,我們經(jīng)常會執(zhí)著于為什么通信三次才可以建立連接溉贿,而不是兩次或者四次;討論使用更多的通信次數(shù)來建立連接往往是沒有意義的浦旱,因?yàn)槲覀兛偪梢?strong>使用更多的通信次數(shù)交換相同的信息宇色,所以使用四次、五次或者更多次數(shù)建立連接在技術(shù)上都是完全可以實(shí)現(xiàn)的颁湖。

basic-3-way-handshake

這種增加 TCP 連接通信次數(shù)的問題往往沒有討論的必要性宣蠕,我們追求的其實(shí)是用更少的通信次數(shù)(理論上的邊界)完成信息的交換,也就是為什么我們在上兩節(jié)中也一再強(qiáng)調(diào)使用『兩次握手』沒有辦法建立 TCP 連接甥捺,使用三次握手是建立連接所需要的最小次數(shù)抢蚀。

總結(jié)

我們在這篇文章中討論了為什么 TCP 建立連接需要經(jīng)過三次握手,在具體分析這個問題之前涎永,我們首先重新思考了 TCP 連接究竟是什么思币,RFC 793 - Transmission Control Protocol - IETF Tools 對 TCP 連接有著非常清楚的定義 —— 用于保證可靠性和流控制機(jī)制的數(shù)據(jù),包括 Socket羡微、序列號以及窗口大小谷饿。

TCP 建立連接時通過三次握手可以有效地避免歷史錯誤連接的建立,減少通信雙方不必要的資源消耗妈倔,三次握手能夠幫助通信雙方獲取初始化序列號博投,它們能夠保證數(shù)據(jù)包傳輸?shù)牟恢夭粊G,還能保證它們的傳輸順序盯蝴,不會因?yàn)榫W(wǎng)絡(luò)傳輸?shù)膯栴}發(fā)生混亂毅哗,到這里不使用『兩次握手』和『四次握手』的原因已經(jīng)非常清楚了:

  • 『兩次握手』:無法避免歷史錯誤連接的初始化听怕,浪費(fèi)接收方的資源;
  • 『四次握手』:TCP 協(xié)議的設(shè)計可以讓我們同時傳遞 ACKSYN 兩個控制信息虑绵,減少了通信次數(shù)尿瞭,所以不需要使用更多的通信次數(shù)傳輸相同的信息;

我們重新回到在文章開頭提的問題翅睛,為什么使用類比解釋 TCP 使用三次握手是錯誤的声搁?這主要還是因?yàn)椋@個類比沒有解釋清楚核心問題 —— 避免歷史上的重復(fù)連接捕发。到最后疏旨,我們還是來看一些比較開放的相關(guān)問題,有興趣的讀者可以仔細(xì)想一下下面的問題:

  • 除了使用序列號是否還有其他方式保證消息的不重不丟扎酷?
  • UDP 協(xié)議有連接的概念么檐涝,它能保證數(shù)據(jù)傳輸?shù)目煽棵矗?/li>

如果對文章中的內(nèi)容有疑問或者想要了解更多軟件工程上一些設(shè)計決策背后的原因,可以在博客下面留言法挨,作者會及時回復(fù)本文相關(guān)的疑問并選擇其中合適的主題作為后續(xù)的內(nèi)容谁榜。

Reference

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市坷剧,隨后出現(xiàn)的幾起案子惰爬,更是在濱河造成了極大的恐慌,老刑警劉巖惫企,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件撕瞧,死亡現(xiàn)場離奇詭異,居然都是意外死亡狞尔,警方通過查閱死者的電腦和手機(jī)丛版,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來偏序,“玉大人页畦,你說我怎么就攤上這事⊙腥澹” “怎么了豫缨?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長端朵。 經(jīng)常有香客問我好芭,道長,這世上最難降的妖魔是什么冲呢? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任舍败,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘邻薯。我一直安慰自己裙戏,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布厕诡。 她就那樣靜靜地躺著累榜,像睡著了一般。 火紅的嫁衣襯著肌膚如雪灵嫌。 梳的紋絲不亂的頭發(fā)上信柿,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天,我揣著相機(jī)與錄音醒第,去河邊找鬼。 笑死进鸠,一個胖子當(dāng)著我的面吹牛稠曼,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播客年,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼霞幅,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了量瓜?” 一聲冷哼從身側(cè)響起司恳,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎绍傲,沒想到半個月后扔傅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡烫饼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年猎塞,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片杠纵。...
    茶點(diǎn)故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡荠耽,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出比藻,到底是詐尸還是另有隱情铝量,我是刑警寧澤,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布银亲,位于F島的核電站慢叨,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏群凶。R本人自食惡果不足惜插爹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧赠尾,春花似錦力穗、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至寸宵,卻和暖如春崖面,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背梯影。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工巫员, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人甲棍。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓简识,卻偏偏與公主長得像,于是被迫代替她去往敵國和親感猛。 傳聞我的和親對象是個殘疾皇子七扰,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評論 2 354

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