成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

TCP沒(méi)那么難吧?這篇一定要看

網(wǎng)絡(luò) 通信技術(shù)
TCP相關(guān)的知識(shí)重要嗎?我覺(jué)得挺重要的,這些年來(lái)無(wú)論互聯(lián)網(wǎng)怎么變化,TCP協(xié)議本身都可以承載,仔細(xì)探究會(huì)發(fā)現(xiàn)它的設(shè)計(jì)的確夠巧妙,有許多值得借鑒的設(shè)計(jì)思想。
[[242081]]
2013年,慕尼黑

如今相當(dāng)多的程序員都是“互聯(lián)網(wǎng)程序員”,按說(shuō),應(yīng)該對(duì)互聯(lián)網(wǎng)的基礎(chǔ)協(xié)議相當(dāng)清楚。可惜至少就我的面試經(jīng)驗(yàn)來(lái)看,許多人這方面缺課太多,簡(jiǎn)單說(shuō)說(shuō)TCP/IP協(xié)議分層就已經(jīng)難倒了不少人。至于TCP/IP的“三次握手”,能說(shuō)上來(lái)的人就相當(dāng)少了,如果再問(wèn)問(wèn)“為什么是三次握手”,基本就沒(méi)人能答上來(lái)了。一般的回答都是“這個(gè)太難”,或者“畢業(yè)太久,這個(gè)忘記了”。

如果臨時(shí)抱佛腳,把TCP的三次握手背下來(lái)應(yīng)付面試,確實(shí)能做到。但是要回答TCP為什么是三次握手,而不是兩次或者四次握手,光靠背就不行了——不信你去網(wǎng)絡(luò)上搜搜看,各種回答都有,眾說(shuō)紛紜,不少提問(wèn)者一頭霧水。

TCP相關(guān)的知識(shí)重要嗎?我覺(jué)得挺重要的,這些年來(lái)無(wú)論互聯(lián)網(wǎng)怎么變化,TCP協(xié)議本身都可以承載,仔細(xì)探究會(huì)發(fā)現(xiàn)它的設(shè)計(jì)的確夠巧妙,有許多值得借鑒的設(shè)計(jì)思想。

那么TCP真的很難嗎?為什么許多人背TCP的握手流程痛苦不堪,復(fù)述起來(lái)困難重重?我覺(jué)得,原因在于大家只把它當(dāng)成“既存事實(shí)”, 就像上中學(xué)時(shí)候背歷史政治那樣對(duì)待。但TCP可不是毫無(wú)邏輯的胡說(shuō),一旦 你搞清了設(shè)計(jì)思想和邏輯,就會(huì)發(fā)現(xiàn)理解起來(lái)一點(diǎn)也不困難。所以,今天我來(lái)做個(gè)簡(jiǎn)單講解。

首先說(shuō)說(shuō)“三次握手”這個(gè)譯名,我確實(shí)覺(jué)得翻譯有誤(翻譯出版過(guò)一百多萬(wàn)字技術(shù)資料,我自信還是有把握的)。我以前總記不住“三次握手”的過(guò)程,因?yàn)榭傆X(jué)得“握了三次手”,“握手”是雙方共同往中間湊的過(guò)程,這明顯和建連流程不符合。后來(lái)才發(fā)現(xiàn),“三次握手”的說(shuō)法大概有問(wèn)題。

“三次握手”的原文是three-way handshake,three-way更合適的翻譯恐怕是“三步”,所以整個(gè)名詞的意思是“需要三個(gè)步驟才能建立握手的機(jī)制”。這么解釋的好處是,“步”給人感覺(jué)更形象,就是“單方面邁一步”而已。實(shí)際上,RFC 793里說(shuō)明了,握手過(guò)程也可以叫three-message handshake,通過(guò)三條消息來(lái)建立的握手。

那么,為什么要三步才能建立握手呢?我們可以暫時(shí)不理這個(gè)問(wèn)題,想想如果我們自己來(lái)設(shè)計(jì)握手機(jī)制,應(yīng)當(dāng)怎么辦。

我們都知道,TCP是可靠的通訊協(xié)議,其“可靠性”就在于,任何一方要向另一方發(fā)數(shù)據(jù)(SYN),都必須收到確認(rèn)回應(yīng)(ACK)。同時(shí)TCP也是雙向的通訊協(xié)議,所以通訊的兩方都可以主動(dòng)發(fā)送消息。

這里要澄清的一點(diǎn),對(duì)許多“互聯(lián)網(wǎng)程序員”來(lái)說(shuō),TCP是掩蓋在HTTP之下的,大家熟悉的HTTP,它的經(jīng)典通訊模式是“一問(wèn)一答”的,沒(méi)有請(qǐng)求就沒(méi)有應(yīng)答。不過(guò)這只是HTTP的特性,不是TCP的特性。在TCP協(xié)議里,客戶端和服務(wù)器都可以隨時(shí)主動(dòng)向?qū)Ψ桨l(fā)送數(shù)據(jù)——也正是因?yàn)槿绱耍挠肏TTP/2之后服務(wù)器可以主動(dòng)推送信息給客戶端,而不必改動(dòng)TCP協(xié)議。

回到TCP,既然它是雙向、可靠的通訊,可以想見(jiàn),建立連接就必須確認(rèn)雙方到對(duì)方的通訊都是可靠的,所以大概需要四步,發(fā)送四次消息。

 

如果軟件設(shè)計(jì)都這么簡(jiǎn)單,那就太好了。可惜,世界上沒(méi)有那么簡(jiǎn)單的事情。仔細(xì)觀察這幅圖,我們會(huì)發(fā)現(xiàn)幾個(gè)問(wèn)題:

***,網(wǎng)絡(luò)通訊的成本是很高的,延遲往往無(wú)法預(yù)測(cè),哪怕能少發(fā)送一次消息,也可以大大降低成本,提高效率。所以,建立連接的步驟上限應(yīng)當(dāng)是四步,下限是兩步,越少越好。

第二,兩輪SYN/ACK之間必須有關(guān)聯(lián),因?yàn)樗鼈兊墓δ芟鄬?duì)獨(dú)立,都是確認(rèn)到對(duì)方的通訊可靠,卻同屬于一個(gè)“建立連接”的邏輯操作。如果兩輪完全獨(dú)立,那么如果兩輪中間間隔了特別特別長(zhǎng)的時(shí)間,根本不是一個(gè)正常的建立連接的操作,程序卻無(wú)法識(shí)別,這顯然是不行的。所以,第二輪SYN/ACK必須要能夠和***輪SYN/ACK關(guān)聯(lián)起來(lái)。

再仔細(xì)看看,第二步和第三步都是從服務(wù)端給客戶端發(fā)消息,所以是不是可以合并起來(lái)?這樣起碼可以節(jié)省了一次網(wǎng)絡(luò)通訊。

 

像上面這樣直接在第二步把ACK和SYN合并起來(lái),問(wèn)題就解決了?

按照之前的分析,節(jié)省消息發(fā)送次數(shù)只是考慮之一,還需要考慮的是,第二輪SYN/ACK必須和***輪SYN/ACK掛鉤。

 

上面是TCP的數(shù)據(jù)報(bào),包含了許多的控制位,用來(lái)標(biāo)識(shí)連接的狀態(tài)。其中最常見(jiàn)的是SYN、ACK、FIN:SYN表示synchronize,在建立連接時(shí)使用;ACK表示acknowledge,表示“確認(rèn)”收到了消息;FIN表示finish,在斷開(kāi)連接時(shí)使用。

還要注意的兩個(gè)東西是SEQ NO和ACK NO。SEQ NO即Sequence Number,服務(wù)端和客戶端都會(huì)維護(hù)自己的SEQ NO,表示“已經(jīng)發(fā)送了多少數(shù)據(jù)”,單位是字節(jié);ACK NO即Acknowledge Number,用來(lái)回復(fù)確認(rèn),對(duì)應(yīng)SEQ NO的數(shù)據(jù)已經(jīng)收到。單獨(dú)說(shuō)起來(lái),這些概念都容易理解,只是注意不要混淆控制位的ACK和ACK NO——ACK是布爾值用來(lái)標(biāo)識(shí)數(shù)據(jù)報(bào)的類型,ACK NO是數(shù)值用來(lái)確認(rèn)已經(jīng)收到的數(shù)據(jù)。

基于上面的知識(shí)我們可以知道,在建立連接之初,數(shù)據(jù)報(bào)中的控制位SYN應(yīng)當(dāng)設(shè)定為1,表示“新建連接”;同時(shí)應(yīng)當(dāng)包含SEQ NO。此時(shí)的SEQ NO有個(gè)專門的名字叫ISN,也就是Initial Sequence Number(要注意,ISN只是用來(lái)稱呼這個(gè)特殊SEQ NO,并不存在專門的ISN字段)。

在服務(wù)端收到***個(gè)SYN消息的時(shí)候,它當(dāng)然需要發(fā)送ACK響應(yīng),但它如何確認(rèn)其中的SEQ NO“就是”新建連接的ISN,而不是來(lái)自?shī)檴檨?lái)遲的某個(gè)古老連接呢?所以必須向客戶端確認(rèn)。恰恰因?yàn)榈诙绞茿CK,SYN“合二為一”的獨(dú)特響應(yīng),所以收到這個(gè)消息時(shí),客戶端就知道,既需要響應(yīng)其中的SYN,也需要核實(shí)其中的ACK(如果你仔細(xì)讀過(guò)RFC793就會(huì)知道,其中專門有一段提到了: A three way handshake is necessary because…… )

到了第三步,客戶端返回的消息里既包含對(duì)應(yīng)SYN的ACK,表示收到了服務(wù)端的消息,同時(shí)設(shè)定SEQ NO=ISN+1,確認(rèn)核實(shí)了ISN。服務(wù)端收到這條消息,確認(rèn)無(wú)誤是要建立新連接。至此,連接建立完畢。

 

大流程看起來(lái)就是這樣,也不難理解。不過(guò)仔細(xì)想想,還是有不少問(wèn)題得考慮的。比如狀態(tài)問(wèn)題,既然TCP是網(wǎng)絡(luò)通訊,會(huì)發(fā)生延遲,那么在“信息已經(jīng)發(fā)送,但還沒(méi)有收到確認(rèn)”的時(shí)候,應(yīng)當(dāng)是有個(gè)明確狀態(tài)的,否則會(huì)發(fā)生狀態(tài)的錯(cuò)亂。實(shí)際上TCP也確實(shí)做到了這點(diǎn),它背后有一臺(tái)完整的狀態(tài)機(jī),確保每時(shí)每刻,每個(gè)動(dòng)作發(fā)生之后,狀態(tài)都完全可控,一切盡在掌握,不會(huì)出現(xiàn)任何“孤點(diǎn)”和“斷頭路”。

 

上圖是TCP的狀態(tài)轉(zhuǎn)移圖的局部,覆蓋了建立鏈接的狀態(tài),感興趣的讀者可以按照自己實(shí)地走走看(說(shuō)個(gè)題外話,“自己模擬在圖上走走”看起來(lái)土,其實(shí)高科技領(lǐng)域也挺常用。設(shè)計(jì)波音737的時(shí)候,開(kāi)始大家都不知道發(fā)動(dòng)機(jī)怎么擺比較好,設(shè)計(jì)師喬·薩特就在紙上畫出機(jī)身和發(fā)動(dòng)機(jī)的模型,把發(fā)動(dòng)機(jī)模型剪下來(lái)在飛機(jī)各處擺放,最終發(fā)現(xiàn)吊在翼下最合適)。

我在之前關(guān)于軟件設(shè)計(jì)的文章里幾次提到狀態(tài)圖、狀態(tài)轉(zhuǎn)移函數(shù),無(wú)論是用戶生命周期、訂單流轉(zhuǎn)過(guò)程,都可以用這個(gè)工具來(lái)解決。遺憾的是,我發(fā)現(xiàn)還有許多設(shè)計(jì)人員不懂得或者不習(xí)慣用使用它,實(shí)在很可惜。

回到TCP建立連接的過(guò)程,我們還要注意ISN。在建立連接時(shí)必須先確定ISN,通過(guò)它把客戶端和服務(wù)器的計(jì)數(shù)對(duì)齊。通常的教材上說(shuō),ISN是隨機(jī)生成的,這樣就保證了唯一性。 隨機(jī)的目的是保持唯一,但千萬(wàn)不要以為“隨機(jī)就不會(huì)重復(fù)”,簡(jiǎn)單的“取隨機(jī)數(shù)”是很容易碰撞的。所以傳統(tǒng)的“隨機(jī)”方案是維護(hù)一個(gè)時(shí)鐘和一個(gè)32位的計(jì)數(shù)器,時(shí)鐘每過(guò)4毫秒,計(jì)數(shù)器自增1。因?yàn)?^32毫秒就是差不多4個(gè)半小時(shí)(MSL,Max Segment Lifetime),這基本超出了任何數(shù)據(jù)包在網(wǎng)絡(luò)中的可能傳輸時(shí)間,所以可以認(rèn)為這種ISN是***的。

但這種方案也有風(fēng)險(xiǎn),既然這樣的ISN是連續(xù)的,那么中途的惡意程序可能能夠預(yù)測(cè)ISN的生成規(guī)律,從而偽造ISN…… 總之ISN的生成是個(gè)有趣的設(shè)計(jì)問(wèn)題,這里不展開(kāi)了,有興趣可以自己搜索資料閱讀。

我在開(kāi)發(fā)中遇到不少程序員,一旦需要避免重復(fù),就想到“生成隨機(jī)數(shù)”,根本不管隨機(jī)數(shù)也可能碰撞。更有甚者,一旦遇到類似ISN的場(chǎng)合,就想當(dāng)然把初始值設(shè)定為0,真是讓人欲哭無(wú)淚(有沒(méi)有想過(guò)ISN為什么不能設(shè)定為0呢,歡迎留言討論)。

說(shuō)完了建立連接的握手,我們?cè)賮?lái)看終止連接的揮手。通常大家都知道,TCP是“三次握手,四次揮手”(雖然我很不贊成“次”,但既然它已經(jīng)約定俗成,這里還是延用通用的說(shuō)法吧)。那么,為什么要四次才能揮手呢?

知道這個(gè)答案的人比能講清楚“三次握手”的要多。通常的答案都是:TCP是雙向通訊協(xié)議,要結(jié)束連接,雙方都必須發(fā)送終止信號(hào),告訴對(duì)方后續(xù)再?zèng)]有數(shù)據(jù)發(fā)過(guò)來(lái)了,并等待對(duì)方確認(rèn),所以一共需要2+2=4次。

 

如果你之前看過(guò)建立連接的過(guò)程,大概會(huì)有這樣的疑問(wèn):既然建立連接的時(shí)候可以節(jié)省一步,把服務(wù)端返回SYN和ACK合并到一起,那么結(jié)束連接的時(shí)候,是否也可以把服務(wù)端返回的SYN和FIN合并起來(lái),節(jié)省一步呢?

想到了這個(gè)問(wèn)題就值得恭喜,因?yàn)槟悴皇侵粷M足于“知其然”,而希望“知其所以然”。不過(guò)我們也需要想到,既然TCP連接的建立和終止都是同一批人定義的,既然他們能想到在建立連接時(shí)節(jié)省一步,那么他們沒(méi)有理由在終止連接時(shí)不做節(jié)省。之所以沒(méi)有“節(jié)省”,一定是有理由存在的。

沒(méi)錯(cuò),確實(shí)是有理由的,而且這個(gè)理由很好理解,因?yàn)榻⒑徒K止連接的場(chǎng)景是不一樣的。在建立連接之前,客戶端和服務(wù)器端都不會(huì)向?qū)Ψ桨l(fā)送任何數(shù)據(jù),所以在服務(wù)端返回ACK的時(shí)候帶上SYN,客戶端當(dāng)然知道這是從服務(wù)端收到的***個(gè)數(shù)據(jù)包。

而在結(jié)束連接時(shí),客戶端向服務(wù)端發(fā)送FIN,表示“我這邊不會(huì)繼續(xù)發(fā)送數(shù)據(jù)過(guò)來(lái)了”,服務(wù)端響應(yīng)ACK,這都沒(méi)有問(wèn)題。但此時(shí),服務(wù)端之前向客戶端發(fā)送數(shù)據(jù)的操作可能還沒(méi)有完成,服務(wù)端仍然在向客戶端傳輸數(shù)據(jù)。如果服務(wù)端把FIN和ACK合并起來(lái),就會(huì)出現(xiàn)這樣的情況:客戶端的數(shù)據(jù)還沒(méi)有接受完,忽然收到服務(wù)端的消息“后續(xù)沒(méi)有數(shù)據(jù)了,終止連接”。顯然,這種情況不應(yīng)當(dāng)出現(xiàn),所以不能把ACK和FIN合并在一起,所以終止連接必須要四步。

最近和實(shí)習(xí)生聊天,說(shuō)起開(kāi)發(fā)中遇到的各種問(wèn)題,以及對(duì)應(yīng)的模型,大家聽(tīng)得入迷。事后有人問(wèn)我:為什么我們工作中遇不到這么有意思的問(wèn)題呢?我知道,這是個(gè)比較典型的問(wèn)題。其實(shí)答案也很典型:因?yàn)槟銢](méi)有去深究問(wèn)題背后的原型。懂得了背后的原型,就具備了“從已知推導(dǎo)無(wú)知”的本領(lǐng),也具備了“從無(wú)知中發(fā)現(xiàn)已知”的眼光。

我和朋友聊開(kāi)發(fā)有個(gè)共同的判斷:TCP的握手和揮手看起來(lái)簡(jiǎn)單,但真讓如今的開(kāi)發(fā)人員去設(shè)計(jì)握手和揮手流程,估計(jì)有超過(guò)一半的人設(shè)計(jì)不出穩(wěn)定、可靠、高效的握手和揮手流程。這樣說(shuō)來(lái),許多業(yè)務(wù)系統(tǒng)里業(yè)務(wù)層面的通訊極不可靠,協(xié)議設(shè)計(jì)錯(cuò)漏百出,也是無(wú)奈的結(jié)果了。

補(bǔ)充一句。我曾在面試中遇到過(guò)這樣的人,非名校畢業(yè),已經(jīng)有五年工作經(jīng)驗(yàn),除了對(duì)流行的框架和熱點(diǎn)問(wèn)題對(duì)答如流,對(duì)數(shù)據(jù)庫(kù)理論、網(wǎng)絡(luò)基礎(chǔ)知識(shí)、數(shù)據(jù)結(jié)構(gòu)和算法依然如數(shù)家珍。事實(shí)充分證明,不是所有人工作之后就把大學(xué)的知識(shí)丟個(gè)精光的,事實(shí)也證明,這樣的候選人確實(shí)能擔(dān)大任。

責(zé)任編輯:未麗燕 來(lái)源: 余晟以為
相關(guān)推薦

2018-11-27 15:55:21

TCP通訊協(xié)議

2018-09-04 15:10:40

2022-06-13 09:26:41

Promise前端代碼

2019-05-17 09:33:50

圖像識(shí)別三維重建文本識(shí)別

2014-11-03 18:22:53

2012-12-21 09:31:52

Windows 8

2021-07-01 07:34:09

LinuxIO模型

2022-10-17 06:22:36

Anaconda開(kāi)源

2023-10-26 18:22:16

前端CSSFlex 布局

2016-12-12 15:28:01

蘋果移動(dòng)開(kāi)發(fā)者

2019-12-29 23:56:51

Python編程語(yǔ)言開(kāi)發(fā)

2019-11-18 08:58:21

朋友圈自拍信息

2020-08-05 12:10:05

Web編程語(yǔ)言前端

2020-05-21 09:17:51

Vue 3Vue代碼

2015-08-24 14:36:53

2024-04-30 10:40:11

2018-03-16 10:07:30

霍金預(yù)言人工智能

2010-11-19 16:02:42

IT族

2019-03-05 09:21:21

IT黑客Redis

2019-06-25 10:02:44

程序員經(jīng)驗(yàn)編程
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 福利一区视频 | 在线观看www高清视频 | 521av网站 | 国产精品视频免费观看 | 欧美久久久久久久 | 久久专区 | 午夜一级做a爰片久久毛片 精品综合 | 日韩在线观看一区 | 精品国产一区二区三区久久久四川 | 麻豆91av | 中文字幕二区 | 国产视频二区 | 欧美片网站免费 | 精品久久久久久久久久久 | 国产一区免费 | 午夜小视频免费观看 | 在线免费观看a级片 | 性网站免费 | 久久久久国产精品一区二区 | 国产成人精品一区二区三区网站观看 | 欧美日韩一区二区三区四区 | 成人精品国产一区二区4080 | 国产精选一区 | 欧美淫 | 很很干很很日 | 欧美日一区二区 | 国产精品免费在线 | 91麻豆精品国产91久久久久久 | 91久操视频 | 九九视频在线观看视频6 | 日韩一区二区三区视频在线观看 | 精品无码久久久久国产 | 免费成人国产 | av天天干 | 久久成人一区二区三区 | 久久精品一区二区三区四区 | 亚洲精品视频免费观看 | 91视频网址 | 午夜精品网站 | 国产男女猛烈无遮掩视频免费网站 | 午夜精品一区二区三区在线观看 |