偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

TCP沒那么難吧?這篇一定要看

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

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

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

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

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

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

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

那么,為什么要三步才能建立握手呢?我們可以暫時(shí)不理這個(gè)問題,想想如果我們自己來設(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),對許多“互聯(lián)網(wǎng)程序員”來說,TCP是掩蓋在HTTP之下的,大家熟悉的HTTP,它的經(jīng)典通訊模式是“一問一答”的,沒有請求就沒有應(yīng)答。不過這只是HTTP的特性,不是TCP的特性。在TCP協(xié)議里,客戶端和服務(wù)器都可以隨時(shí)主動(dòng)向?qū)Ψ桨l(fā)送數(shù)據(jù)——也正是因?yàn)槿绱?,改用HTTP/2之后服務(wù)器可以主動(dòng)推送信息給客戶端,而不必改動(dòng)TCP協(xié)議。

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

 

如果軟件設(shè)計(jì)都這么簡單,那就太好了??上В澜缟蠜]有那么簡單的事情。仔細(xì)觀察這幅圖,我們會(huì)發(fā)現(xiàn)幾個(gè)問題:

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

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

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

 

像上面這樣直接在第二步把ACK和SYN合并起來,問題就解決了?

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

 

上面是TCP的數(shù)據(jù)報(bào),包含了許多的控制位,用來標(biāo)識連接的狀態(tài)。其中最常見的是SYN、ACK、FIN:SYN表示synchronize,在建立連接時(shí)使用;ACK表示acknowledge,表示“確認(rèn)”收到了消息;FIN表示finish,在斷開連接時(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,用來回復(fù)確認(rèn),對應(yīng)SEQ NO的數(shù)據(jù)已經(jīng)收到。單獨(dú)說起來,這些概念都容易理解,只是注意不要混淆控制位的ACK和ACK NO——ACK是布爾值用來標(biāo)識數(shù)據(jù)報(bào)的類型,ACK NO是數(shù)值用來確認(rèn)已經(jīng)收到的數(shù)據(jù)。

基于上面的知識我們可以知道,在建立連接之初,數(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只是用來稱呼這個(gè)特殊SEQ NO,并不存在專門的ISN字段)。

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

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

 

大流程看起來就是這樣,也不難理解。不過仔細(xì)想想,還是有不少問題得考慮的。比如狀態(tài)問題,既然TCP是網(wǎng)絡(luò)通訊,會(huì)發(fā)生延遲,那么在“信息已經(jīng)發(fā)送,但還沒有收到確認(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í)地走走看(說個(gè)題外話,“自己模擬在圖上走走”看起來土,其實(shí)高科技領(lǐng)域也挺常用。設(shè)計(jì)波音737的時(shí)候,開始大家都不知道發(fā)動(dòng)機(jī)怎么擺比較好,設(shè)計(jì)師喬·薩特就在紙上畫出機(jī)身和發(fā)動(dòng)機(jī)的模型,把發(fā)動(dòng)機(jī)模型剪下來在飛機(jī)各處擺放,最終發(fā)現(xiàn)吊在翼下最合適)。

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

回到TCP建立連接的過程,我們還要注意ISN。在建立連接時(shí)必須先確定ISN,通過它把客戶端和服務(wù)器的計(jì)數(shù)對齊。通常的教材上說,ISN是隨機(jī)生成的,這樣就保證了唯一性。 隨機(jī)的目的是保持唯一,但千萬不要以為“隨機(jī)就不會(huì)重復(fù)”,簡單的“取隨機(jī)數(shù)”是很容易碰撞的。所以傳統(tǒng)的“隨機(jī)”方案是維護(hù)一個(gè)時(shí)鐘和一個(gè)32位的計(jì)數(shù)器,時(shí)鐘每過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ù)測ISN的生成規(guī)律,從而偽造ISN…… 總之ISN的生成是個(gè)有趣的設(shè)計(jì)問題,這里不展開了,有興趣可以自己搜索資料閱讀。

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

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

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

 

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

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

沒錯(cuò),確實(shí)是有理由的,而且這個(gè)理由很好理解,因?yàn)榻⒑徒K止連接的場景是不一樣的。在建立連接之前,客戶端和服務(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ù)過來了”,服務(wù)端響應(yīng)ACK,這都沒有問題。但此時(shí),服務(wù)端之前向客戶端發(fā)送數(shù)據(jù)的操作可能還沒有完成,服務(wù)端仍然在向客戶端傳輸數(shù)據(jù)。如果服務(wù)端把FIN和ACK合并起來,就會(huì)出現(xiàn)這樣的情況:客戶端的數(shù)據(jù)還沒有接受完,忽然收到服務(wù)端的消息“后續(xù)沒有數(shù)據(jù)了,終止連接”。顯然,這種情況不應(yīng)當(dāng)出現(xiàn),所以不能把ACK和FIN合并在一起,所以終止連接必須要四步。

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

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

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

責(zé)任編輯:未麗燕 來源: 余晟以為
相關(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

圖像識別三維重建文本識別

2021-07-01 07:34:09

LinuxIO模型

2014-11-03 18:22:53

2012-12-21 09:31:52

Windows 8

2022-10-17 06:22:36

Anaconda開源

2023-10-26 18:22:16

前端CSSFlex 布局

2016-12-12 15:28:01

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

2019-12-29 23:56:51

Python編程語言開發(fā)

2019-11-18 08:58:21

朋友圈自拍信息

2020-08-05 12:10:05

Web編程語言前端

2015-08-24 14:36:53

2024-04-30 10:40:11

2020-05-21 09:17:51

Vue 3Vue代碼

2018-03-16 10:07:30

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

2010-11-19 16:02:42

IT族

2019-06-25 10:02:44

程序員經(jīng)驗(yàn)編程

2019-03-05 09:21:21

IT黑客Redis
點(diǎn)贊
收藏

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