- 相關(guān)推薦
程序員應(yīng)該了解的網(wǎng)絡(luò)協(xié)議
引導(dǎo)語(yǔ):網(wǎng)絡(luò)協(xié)議是進(jìn)行網(wǎng)絡(luò)連通信的重點(diǎn),以下是小編整理的程序員應(yīng)該了解的網(wǎng)絡(luò)協(xié)議,歡迎參考閱讀!
網(wǎng)絡(luò)路由
在過(guò)去的模擬電話中,撥打電話意味著從電話到朋友那里具有真實(shí)的電線連接。就好像電線直接從你那里連接到他們那里。雖然沒(méi)有這樣實(shí)際的電線,當(dāng)然——連接是通過(guò)復(fù)雜的開(kāi)關(guān)系統(tǒng)進(jìn)行的——但它與電線相當(dāng)。
有太多的Internet節(jié)點(diǎn)可以這樣工作。但是我們不能從每個(gè)機(jī)器到要和其對(duì)話的其他機(jī)器提供直接、不間斷的路徑連接。
相反,數(shù)據(jù)是桶式的,從一個(gè)路由器傳遞到下一個(gè)路由器,在鏈路中,每個(gè)路由器使數(shù)據(jù)更靠近目的地。 我的筆記本電腦和谷歌服務(wù)器之間的每個(gè)路由器連接到其他多個(gè)路由器,這樣維護(hù)著一個(gè)粗略的路由表,顯示哪些路由器更接近互聯(lián)網(wǎng)的哪個(gè)部分。當(dāng)一個(gè)數(shù)據(jù)包到達(dá)的目的地是谷歌服務(wù)器時(shí),路由表中的快速查找功能告訴數(shù)據(jù)包走哪個(gè)路由器能夠更加靠近谷歌服務(wù)器。數(shù)據(jù)包很小,所以鏈路中的每個(gè)路由器只會(huì)對(duì)下一個(gè)路由器占用一小段時(shí)間。
路由解決的問(wèn)題可分為兩個(gè)子問(wèn)題。首先,解決:數(shù)據(jù)的目的地是什么?這由IP、互聯(lián)網(wǎng)協(xié)議、IP地址處理。IPv4仍然是IP的最常見(jiàn)版本,僅提供32位地址空間。現(xiàn)在已完全分配,因此將一個(gè)節(jié)點(diǎn)添加到公共Internet需要重用現(xiàn)有的IP地址。 IPv6允許2128個(gè)地址(約1038個(gè)),但截至2017年只有約20%被使用。
現(xiàn)在我們有地址,我們需要知道如何通過(guò)互聯(lián)網(wǎng)將數(shù)據(jù)包路由到其目的地。路由過(guò)程發(fā)生得很快,所以沒(méi)有時(shí)間查詢遠(yuǎn)程數(shù)據(jù)庫(kù)的路由信息。例如,Cisco ASR 9922路由器的最大容量為每秒160兆比特。假設(shè)完整的1500字節(jié)數(shù)據(jù)包(12,000位),也即是在一個(gè)19英寸機(jī)架中每秒13333333333個(gè)數(shù)據(jù)包!
為了快速路由,路由器維護(hù)路由表,指示各種IP地址組的路徑。當(dāng)新數(shù)據(jù)包到達(dá)時(shí),路由器在表中查找它,告訴它哪個(gè)對(duì)等體最接近目的地。它將數(shù)據(jù)包發(fā)送給該對(duì)等體并移動(dòng)到下一個(gè)。BGP的工作是在不同路由器之間傳遞此路由表信息,確保是最新的路由表。
不幸的是,IP和BGP一起并不能搭建有效的網(wǎng)絡(luò),因?yàn)樗鼈儧](méi)有辦法可靠地傳輸數(shù)據(jù)。如果路由器過(guò)載并丟包,我們需要一種方法來(lái)檢測(cè)丟失并請(qǐng)求重傳。
分組交換
如果互聯(lián)網(wǎng)通過(guò)路由器將網(wǎng)絡(luò)中彼此之間的數(shù)據(jù)相互連接起來(lái),那么當(dāng)數(shù)據(jù)量大時(shí)會(huì)發(fā)生什么? 如果我們請(qǐng)求88.5 MB的JavaScript Birth & Death視頻,應(yīng)該怎么辦?
我們可以嘗試設(shè)計(jì)一個(gè)網(wǎng)絡(luò),其中88.5 MB文檔從Web服務(wù)器發(fā)送到第一個(gè)路由器,然后到第二個(gè),以此類(lèi)推。不幸的是,該網(wǎng)絡(luò)在互聯(lián)網(wǎng)規(guī)模上甚至內(nèi)部網(wǎng)絡(luò)規(guī)模都無(wú)法工作。
首先,計(jì)算機(jī)是具有有限存儲(chǔ)量的有限個(gè)機(jī)器。如果一個(gè)給定的路由器只有88.4 MB的緩沖區(qū)可用,它根本不能存儲(chǔ)88.5 MB的視頻文件。因此數(shù)據(jù)將被丟棄,更糟糕的是,這沒(méi)有任何跡象。如果路由器十分繁忙而丟失數(shù)據(jù),那么無(wú)法花時(shí)間告訴我丟棄的數(shù)據(jù)。
二是電腦不可靠。有時(shí),路由節(jié)點(diǎn)失敗。 有時(shí),船舶的錨點(diǎn)會(huì)意外損壞關(guān)乎大量互聯(lián)網(wǎng)數(shù)據(jù)的水下光纖電纜。
由于這些原因,我們不會(huì)通過(guò)互聯(lián)網(wǎng)發(fā)送88.5 MB的郵件。相反,我們將它們分解成數(shù)據(jù)包,通常在每個(gè)1,400字節(jié)左右。我們的視頻文件將分為63,214個(gè)單獨(dú)的數(shù)據(jù)包進(jìn)行傳輸。
無(wú)序數(shù)據(jù)包
通過(guò)數(shù)據(jù)包捕獲工具Wireshark測(cè)量JavaScript的Birth & Death實(shí)際傳輸情況,我收到的總共接收到61,807個(gè)數(shù)據(jù)包,每個(gè)是1,432個(gè)字節(jié)。將這兩個(gè)相乘,我們得到88.5兆字節(jié)數(shù)據(jù),這是視頻的大小。(這不包括各種協(xié)議增加的開(kāi)銷(xiāo),如果包括,我們會(huì)看到稍高一些的數(shù)據(jù)大。
傳輸是通過(guò)HTTP完成的,一種通過(guò)TCP分層的協(xié)議,即傳輸控制協(xié)議。它只需要14秒,因此數(shù)據(jù)包的平均速率約為每秒4,400,或每包約250微秒。在14秒鐘內(nèi),我的機(jī)器收到全部的61,807個(gè)數(shù)據(jù)包,可能是無(wú)序的,當(dāng)它們進(jìn)來(lái)時(shí)將它們重新組裝成完整的文件。
使用最簡(jiǎn)單的機(jī)制重新組裝TCP包,可以想象:一個(gè)計(jì)數(shù)器。每個(gè)數(shù)據(jù)包發(fā)送時(shí)都會(huì)分配一個(gè)序列號(hào)。在接收端,按照序列號(hào)對(duì)數(shù)據(jù)包進(jìn)行排序。一旦這一切都順利,沒(méi)有差別,我們知道文件是完整的。(實(shí)際的TCP序列號(hào)往往不是整數(shù),每次只增加1,但這個(gè)細(xì)節(jié)在這里并不重要。)
我們?cè)趺粗牢募螘r(shí)完成?TCP并不能回答,因?yàn)檫@是更高級(jí)協(xié)議的工作。例如,HTTP會(huì)有包含一個(gè)“Content-Length”頭,指定響應(yīng)長(zhǎng)度(以字節(jié)為單位)?蛻舳俗x取Content-Length,然后繼續(xù)讀取TCP數(shù)據(jù)包,將其組裝成原始順序,直到它具有Content-Length指定的長(zhǎng)度。這就是HTTP頭(和大多數(shù)其他協(xié)議頭)先于響應(yīng)有效負(fù)載到來(lái)的一個(gè)原因:否則,我們不知道有效負(fù)載的大小。
當(dāng)我們?cè)谶@里說(shuō)“客戶”時(shí),我們實(shí)際上在談?wù)撜麄(gè)電腦接收端。TCP重組發(fā)生在內(nèi)核內(nèi)部,因此Web瀏覽器和curl和wget等應(yīng)用程序不必手動(dòng)重新組合TCP數(shù)據(jù)包。但內(nèi)核不處理HTTP,因此應(yīng)用程序必須了解Content-Length頭文件,并知道要讀取的字節(jié)數(shù)。
使用序列號(hào)和分組重新排序,即使數(shù)據(jù)包無(wú)序到達(dá),我們也可以發(fā)送大的字節(jié)序列。但是如果一個(gè)數(shù)據(jù)包在傳輸中丟失了,會(huì)在HTTP響應(yīng)中留下一個(gè)空白嗎?
傳輸窗口和慢啟動(dòng)
我們一邊開(kāi)著Wireshark,一邊下載“Death and Death of JavaScript”。通過(guò)瀏覽捕獲的結(jié)果,我們看到源源不斷的數(shù)據(jù)包被接收到。
例如,序列號(hào)為563,321的數(shù)據(jù)包到達(dá)。像所有TCP數(shù)據(jù)包一樣,它有一個(gè)“下一個(gè)序列號(hào)”,它是用于下一個(gè)數(shù)據(jù)包的數(shù)字。該數(shù)據(jù)包的“下一個(gè)序列號(hào)”為564,753。事實(shí)上,下一個(gè)數(shù)據(jù)包的序列號(hào)也的確為564,753,所以一切都很好。當(dāng)連接達(dá)到一定速度后,每秒鐘會(huì)發(fā)生數(shù)千次傳輸。
有時(shí)候,我的電腦會(huì)向服務(wù)器發(fā)送一條消息,例如“我已收到所有數(shù)據(jù)包,包括數(shù)據(jù)包564,753”。這是一個(gè)ACK,用于確認(rèn):我的電腦確認(rèn)收到服務(wù)器的數(shù)據(jù)包。在一個(gè)新的連接上,Linux內(nèi)核每十個(gè)數(shù)據(jù)包發(fā)送一個(gè)ACK。這由TCP_INIT_CWND常量控制,我們可以在Linux內(nèi)核的源代碼中定義它們。(TCP_INIT_CWND中的CWND表示擁塞窗口:一次允許的數(shù)據(jù)量)如果網(wǎng)絡(luò)擁塞(超載),窗口大小將減少,傳輸數(shù)據(jù)包變慢)。
十個(gè)數(shù)據(jù)包大約是14 KB,所以我們一次限制在14 KB數(shù)據(jù)。這是TCP慢啟動(dòng)的一部分:連接從小擁塞窗口開(kāi)始。如果沒(méi)有數(shù)據(jù)包丟失,接收機(jī)將不斷增加擁塞窗口,允許一次傳輸更多的數(shù)據(jù)包。
有時(shí),數(shù)據(jù)包將發(fā)生丟失,所以接收窗口會(huì)縮小,傳輸速度變慢。通過(guò)自動(dòng)調(diào)整擁塞窗口以及一些其他參數(shù),發(fā)送方和接收方保持?jǐn)?shù)據(jù)移動(dòng)速度在網(wǎng)絡(luò)允許的情況下盡可能快,但不會(huì)超出限制。
這種情況發(fā)生在連接的兩端:每一方都會(huì)確認(rèn)對(duì)方的消息,并且每一方都保留自己的擁塞窗口。非對(duì)稱窗口允許協(xié)議充分利用具有不對(duì)稱上行和下行帶寬的網(wǎng)絡(luò)連接,比如大多數(shù)住宅和移動(dòng)互聯(lián)網(wǎng)連接。
可靠傳輸
電腦不可靠:由計(jì)算機(jī)組成的網(wǎng)絡(luò)是不可靠的。在像因特網(wǎng)這樣的大型網(wǎng)絡(luò)中,故障是運(yùn)行的正常部分,必須適應(yīng)。在分組網(wǎng)絡(luò)中,這意味著重傳:如果客戶端接收到數(shù)據(jù)包1和3,但沒(méi)有接收到2,則需要請(qǐng)求服務(wù)器重新發(fā)送丟失的數(shù)據(jù)包。
當(dāng)每秒接收數(shù)千個(gè)數(shù)據(jù)包時(shí),如我們的88.5 MB視頻下載,錯(cuò)誤幾乎是必然的。為了證明,讓我們回到我的Wireshark捕獲的下載。對(duì)于數(shù)千個(gè)數(shù)據(jù)包,一切正常。每個(gè)數(shù)據(jù)包指定一個(gè)“下一個(gè)序列號(hào)”,后面是另一個(gè)包含該數(shù)字的數(shù)據(jù)包。
突然間出了問(wèn)題。第6,269個(gè)數(shù)據(jù)包具有7,208,745的“下一個(gè)序列號(hào)”,但該數(shù)據(jù)包一直沒(méi)有到來(lái)。相反,序列號(hào)為7,211,609的數(shù)據(jù)包到達(dá)。這是一個(gè)亂序的數(shù)據(jù)包:意味著缺少一些東西。
我們不清楚這里出了什么問(wèn)題,也許互聯(lián)網(wǎng)上的一個(gè)中間路由器過(guò)載,也許我的本地路由器超載,也許有人使用微波爐,引入電磁干擾并減慢了我的無(wú)線連接。在任何情況下,數(shù)據(jù)包丟失,唯一的指示是接收到意外的數(shù)據(jù)包。
TCP沒(méi)有特殊的“我丟了一個(gè)包!”信息。相反,ACK被巧妙地用于指示丟失。當(dāng)出現(xiàn)亂序的數(shù)據(jù)包時(shí),接收機(jī)會(huì)re-ACK最后一個(gè)好的數(shù)據(jù)包——即正確順序的最后一個(gè)數(shù)據(jù)包。實(shí)際上,接收機(jī)正在說(shuō)“我收到了我正在確認(rèn)的數(shù)據(jù)包5,之后也收到了一些信息,但是我知道它不是數(shù)據(jù)包6,因?yàn)樗c數(shù)據(jù)包5中的下一個(gè)序列號(hào)不匹配。
如果兩個(gè)數(shù)據(jù)包在傳輸過(guò)程中被交換了順序,則會(huì)導(dǎo)致單個(gè)額外的ACK,并且在收到無(wú)序數(shù)據(jù)包后,所有內(nèi)容都將繼續(xù)正常傳輸。但是如果數(shù)據(jù)包真的丟失,意外的數(shù)據(jù)包將繼續(xù)到達(dá),并且接收器將繼續(xù)發(fā)送最后一個(gè)好數(shù)據(jù)包的ACK副本。這可能導(dǎo)致數(shù)百個(gè)重復(fù)的ACK。
當(dāng)發(fā)送方在一行中看到三個(gè)重復(fù)的ACK時(shí),它假定下一個(gè)數(shù)據(jù)包丟失并重發(fā)。這被稱為T(mén)CP快速重傳,因?yàn)樗纫郧盎诔瑫r(shí)的方法更快。有趣的是,協(xié)議本身沒(méi)有任何明確的方式說(shuō)“請(qǐng)立即重發(fā)!”相反,協(xié)議產(chǎn)生的多個(gè)ACK自然用作了觸發(fā)器。(一個(gè)有趣的思考實(shí)驗(yàn):如果一些重復(fù)的ACK丟失,從未到達(dá)發(fā)送者,會(huì)發(fā)生什么?)
即使網(wǎng)絡(luò)正常工作,重傳也是很常見(jiàn)的。在我們的88.5 MB視頻下載中,我看到了這一點(diǎn):
由于持續(xù)成功的傳輸,擁塞窗口迅速增加到大約一兆字節(jié);
1)有幾千個(gè)包順序出現(xiàn),一切正常;
2)一個(gè)數(shù)據(jù)包發(fā)生故障;
3)數(shù)據(jù)繼續(xù)以兆字節(jié)/秒計(jì)算,但數(shù)據(jù)包仍然丟失;
4)我的機(jī)器發(fā)送最后一個(gè)已知好數(shù)據(jù)包的數(shù)十個(gè)重復(fù)的ACK,但是內(nèi)核還存儲(chǔ)待處理的無(wú)序數(shù)據(jù)包以供稍后重新組裝;
5)服務(wù)器接收重復(fù)的ACK并重新發(fā)送丟失的數(shù)據(jù)包;
6)我的客戶端對(duì)以前丟失的數(shù)據(jù)包和隨后由于無(wú)序傳輸已經(jīng)收到的數(shù)據(jù)包進(jìn)行ACK。這是通過(guò)簡(jiǎn)單地確認(rèn)最近的數(shù)據(jù)包來(lái)完成的,這個(gè)數(shù)據(jù)包也隱含地對(duì)所有較早的數(shù)據(jù)進(jìn)行ACK。
7)傳輸繼續(xù),但是由于丟失的數(shù)據(jù)包,擁塞窗口縮小。
這個(gè)是正常的,這是發(fā)生在我所完成的完整下載的每個(gè)捕獲中。盡管我們認(rèn)為日常生活中網(wǎng)絡(luò)是不可靠的,甚至TCP在正常條件下也會(huì)偶爾失敗,但是TCP仍然是工作得很出色的。
物理網(wǎng)絡(luò)
所有這些網(wǎng)絡(luò)數(shù)據(jù)必須通過(guò)物理介質(zhì)(如銅纜,光纖和無(wú)線電)傳輸。在物理層協(xié)議中,以太網(wǎng)是最為人所知的。在互聯(lián)網(wǎng)的早期,它的受歡迎程度使我們?cè)O(shè)計(jì)其他協(xié)議以適應(yīng)其限制。
首先,讓我們認(rèn)識(shí)物理細(xì)節(jié)。以太網(wǎng)與RJ45連接器關(guān)系最為緊密,RJ45連接器看起來(lái)像更大的八針版本的老式四針手機(jī)插孔。它還與cat5(或cat5e或cat6或cat7)電纜相關(guān)聯(lián),其中包含絞合成四對(duì)的八根總線。這里還存在其他媒體,如我們最有可能在家中遇到的:八根電線纏繞在與8針插孔相連的護(hù)套中。
以太網(wǎng)是物理層協(xié)議:它描述了這些位如何變成電纜中的電信號(hào)。它也是一個(gè)鏈路層協(xié)議:它描述了一個(gè)節(jié)點(diǎn)與另一個(gè)節(jié)點(diǎn)的直接連接。但是,它純粹是點(diǎn)對(duì)點(diǎn)的,并且與數(shù)據(jù)在網(wǎng)絡(luò)上的路由無(wú)關(guān)。在這一層沒(méi)有TCP概念中的鏈接概念,也沒(méi)有IP地址意義上的可重新分配地址的概念。
作為協(xié)議,以太網(wǎng)有兩個(gè)主要的工作。首先,每個(gè)設(shè)備需要注意它連接的設(shè)備,需要協(xié)商一些連接速度等參數(shù)。
第二,一旦鏈路建立,以太網(wǎng)需要攜帶數(shù)據(jù)。像較高級(jí)協(xié)議如TCP和IP一樣,以太網(wǎng)數(shù)據(jù)被分解成數(shù)據(jù)包。數(shù)據(jù)包的核心是一個(gè)幀,它有一個(gè)1500字節(jié)的有效載荷,再加上另外22個(gè)字節(jié)的頭信息,如源和目標(biāo)MAC地址,有效載荷長(zhǎng)度和校驗(yàn)和。經(jīng)常處理地址長(zhǎng)度與校驗(yàn)和的程序員對(duì)這些領(lǐng)域是很熟悉的,我們可以想象為什么它們是必要的。
然后將幀包含在另一層的header中以形成完整數(shù)據(jù)包,但這些header很奇怪。他們開(kāi)始與模擬電氣系統(tǒng)的基礎(chǔ)現(xiàn)實(shí)相反,所以他們看起來(lái)似乎不會(huì)被放在軟件協(xié)議中。完整的以太網(wǎng)數(shù)據(jù)包包含:
1)前導(dǎo)碼是56位(7字節(jié))的交替1和0。設(shè)備使用它來(lái)同步他們的時(shí)鐘,就像當(dāng)人們計(jì)數(shù)“1-2-3-GO!”時(shí)一樣。計(jì)算機(jī)無(wú)法計(jì)數(shù)超過(guò)1,所以他們通過(guò)說(shuō)“101010101010101010101010101010101010101010101010101010”進(jìn)行同步。
2)8位(1字節(jié))起始幀分隔符,為171(10101011為二進(jìn)制),這標(biāo)志著前導(dǎo)碼的結(jié)束。請(qǐng)注意,再次重復(fù)“10”,直到“11”為止。
3)如上所述,幀本身包含源和目的地址,有效載荷等。
4)96位(12字節(jié))的間隔間隙,其中l(wèi)ine處于空閑狀態(tài)。大概這是讓設(shè)備休息,因?yàn)樗鼈兒芾邸?/p>
把這一切放在一起:我們想要的是傳輸我們的1500字節(jié)的數(shù)據(jù)。我們添加22個(gè)字節(jié)來(lái)創(chuàng)建一個(gè)幀,它指示源,目標(biāo),大小和校驗(yàn)和。我們?cè)偬砑?0個(gè)字節(jié)的額外數(shù)據(jù)來(lái)滿足硬件需求,創(chuàng)建完整的以太網(wǎng)數(shù)據(jù)包。
你可能認(rèn)為這就是堆棧的底層。并不是這樣,反而因?yàn)槟M世界變得越來(lái)越復(fù)雜,堆棧底層也變得越來(lái)越復(fù)雜。
當(dāng)網(wǎng)絡(luò)遇見(jiàn)現(xiàn)實(shí)世界
數(shù)字系統(tǒng)不是真實(shí)存在的;所有一切都是模擬的。
假設(shè)我們有一個(gè)5伏CMOS系統(tǒng)。(CMOS是一種數(shù)字系統(tǒng),如果你不熟悉也不用擔(dān)心)這意味著一個(gè)完全開(kāi)啟的信號(hào)將是5伏,一個(gè)完全關(guān)閉的信號(hào)將是0。但沒(méi)有什么是永遠(yuǎn)完全關(guān)閉或完全關(guān)閉的,因?yàn)槲锢硎澜绮辉试S。實(shí)際上,我們的5伏CMOS系統(tǒng)將會(huì)考慮將高于1.67伏的任何值記為1,而低于1.67的任何值都將為0。(1.67是5的1/3,我們不用擔(dān)心為什么閾值是1/3,如果你想深入研究,維基百科有一篇相關(guān)文章!而且,以太網(wǎng)不是CMOS甚至不與CMOS相關(guān),CMOS和其1/3的值僅用于簡(jiǎn)單的說(shuō)明。)
我們的以太網(wǎng)數(shù)據(jù)包必須通過(guò)物理線路,這意味著更改電線上的電壓。以太網(wǎng)是一個(gè)5伏系統(tǒng),所以我們期望以太網(wǎng)協(xié)議中的每1位為5伏,每個(gè)0位為0伏。但是有兩個(gè)竅門(mén):首先,電壓范圍是-2.5 V到+2.5 V。其次,更奇妙的是,每組8位在到達(dá)電線之前就會(huì)擴(kuò)展成10位。
有256個(gè)可能的8位值和1024個(gè)可能的10位值,因此可以將其映射到表中。每個(gè)8位字節(jié)可以映射到四個(gè)不同的10位模式中的任一個(gè),每個(gè)模式將被轉(zhuǎn)回到接收端的同一個(gè)8位字節(jié)。例如,10位值00.0000.0000可能映射到8位值0000.0000。但也可能10位的值10.1010.1010也映射到0000.0000。當(dāng)以太網(wǎng)設(shè)備看到00.0000.0000或10.1010.1010時(shí),它們將被理解為字節(jié)0(二進(jìn)制0000.0000)。(警告:現(xiàn)在有一些電子相關(guān)的術(shù)語(yǔ)。)
這是為了提供特別的模擬電路需求:平衡設(shè)備中的電壓。假設(shè)這個(gè)8位到10位編碼不存在,我們發(fā)送一些恰好全是1的數(shù)據(jù)。以太網(wǎng)的電壓范圍為-2.5至+2.5伏,因此我們將以太網(wǎng)電纜的電壓保持在+2.5 V,不斷從另一側(cè)拉電子。
為什么我們關(guān)心一方比另一方更多的電子?因?yàn)槟M世界是混亂的,會(huì)造成各種不良影響。要采取一個(gè):它可以對(duì)低通濾波器中使用的電容器進(jìn)行充電,從而在信號(hào)電平本身產(chǎn)生偏移,最終導(dǎo)致位錯(cuò)誤。這些錯(cuò)誤將需要時(shí)間來(lái)積累,但是我們不希望我們的網(wǎng)絡(luò)設(shè)備在兩年的正常運(yùn)行時(shí)間之后突然破壞數(shù)據(jù),就因?yàn)槲覀兣銮砂l(fā)送了1比0多的二進(jìn)制數(shù)。(電子相關(guān)術(shù)語(yǔ)在這里結(jié)束。)
通過(guò)使用8b / 10b編碼,以太網(wǎng)可以平衡通過(guò)線路發(fā)送的0和1數(shù)量,即使我們發(fā)送大多數(shù)為1或大多數(shù)為0的數(shù)據(jù)。硬件跟蹤0到1的比例,將溢出的8位字節(jié)映射到10位表的不同選項(xiàng),以實(shí)現(xiàn)電氣平衡。(較新的以太網(wǎng)標(biāo)準(zhǔn),如10 GB以太網(wǎng),使用不同的和更復(fù)雜的編碼系統(tǒng)。)
我們就討論到這里,因?yàn)槲覀円呀?jīng)超出了可以被視為編程的范圍,但是還有更多的協(xié)議來(lái)適應(yīng)物理層。在許多情況下,硬件問(wèn)題的解決方案在于軟件本身,如在用于校正DC偏移的8b / 10b編碼的情況下。這對(duì)程序員來(lái)說(shuō)可能有點(diǎn)令人不安:我們喜歡假裝我們的軟件生活在一個(gè)完美的柏拉圖式世界,沒(méi)有粗俗的物理缺陷。實(shí)際上,一切都是模擬的,并且限制著每個(gè)人的工作和軟件的復(fù)雜性。
互聯(lián)網(wǎng)絡(luò)棧
互聯(lián)網(wǎng)協(xié)議最好被理解為層堆棧。以太網(wǎng)提供物理數(shù)據(jù)傳輸和兩個(gè)點(diǎn)對(duì)點(diǎn)設(shè)備之間的鏈接。IP提供了尋址層,允許路由器和大型網(wǎng)絡(luò)存在,但它是無(wú)連接的。分組數(shù)據(jù)被發(fā)射到以太網(wǎng)中,但沒(méi)有指示是否到達(dá)的功能。TCP通過(guò)使用序列號(hào),通過(guò)確認(rèn)和重傳來(lái)添加一層可靠的傳輸。
最后,像HTTP這樣的應(yīng)用層協(xié)議在TCP之上。在這個(gè)層面上,我們能夠?qū)ぶ,并且似乎?shí)現(xiàn)了可靠傳輸和持續(xù)連接。IP和TCP將應(yīng)用程序開(kāi)發(fā)人員從不斷重新實(shí)現(xiàn)數(shù)據(jù)包重傳和尋址等工作中解放出來(lái)。
這些層的獨(dú)立性很重要。例如,當(dāng)我的88.5 MB視頻傳輸丟包時(shí),互聯(lián)網(wǎng)的骨干路由器不知道,只有我的機(jī)器和網(wǎng)絡(luò)服務(wù)器知道。來(lái)自我計(jì)算機(jī)的數(shù)十個(gè)重復(fù)ACK都被完全路由在丟失原始數(shù)據(jù)包的相同路由基礎(chǔ)設(shè)施上。負(fù)責(zé)丟棄丟包路由器的也可能是幾毫秒后更換的路由器。這是理解互聯(lián)網(wǎng)的重要一點(diǎn):路由基礎(chǔ)架構(gòu)并不了解TCP,它只有路線。(雖然有一些例外,但通常是這樣的。)
協(xié)議棧的層獨(dú)立運(yùn)行,但它們不是獨(dú)立設(shè)計(jì)的。更高級(jí)別的協(xié)議往往建立在較低級(jí)別的協(xié)議上:HTTP建立在基于IP的TCP上,IP建立在以太網(wǎng)上。較低層次的設(shè)計(jì)決策往往影響更高層次的決策,甚至影響數(shù)十年后的決策。
以太網(wǎng)是傳統(tǒng)的,涉及到物理層,所以它需要設(shè)置基本參數(shù)。以太網(wǎng)有效載荷最多為1500字節(jié)。
IP包需要配置在以太網(wǎng)幀中。IP具有20字節(jié)的最小報(bào)頭,因此IP數(shù)據(jù)包的最大有效負(fù)載為1,500 - 20 = 1,480字節(jié)。
同樣,TCP分組需要適應(yīng)IP分組。TCP也具有20字節(jié)的最小報(bào)頭,最大TCP有效負(fù)載為1,480 - 20 = 1,460字節(jié)。實(shí)際上,其他header和協(xié)議可以進(jìn)一步減少。1,400是一個(gè)保守的TCP有效載荷大小。
1,400字節(jié)的限制影響現(xiàn)代協(xié)議的設(shè)計(jì)。例如,HTTP請(qǐng)求通常很小,如果我們將它們分配于一個(gè)數(shù)據(jù)包而不是兩個(gè)數(shù)據(jù)包,那么我們可以減少丟失部分請(qǐng)求的可能性,同時(shí)可以減少TCP重傳的可能性。為了從HTTP請(qǐng)求中擠出字節(jié),HTTP / 2指定了頭文件的壓縮,這通常很小。沒(méi)有來(lái)自TCP,IP和以太網(wǎng)的上下文,這似乎很愚蠢:為什么添加到協(xié)議的header壓縮來(lái)只保存幾個(gè)字節(jié)?因?yàn)榘凑誋TTP / 2規(guī)范在第2節(jié)的介紹,壓縮允許“許多請(qǐng)求被壓縮成一個(gè)數(shù)據(jù)包”。
HTTP / 2的header壓縮是為了滿足來(lái)自IP約束的TCP限制,這些限制來(lái)自于20世紀(jì)70年代開(kāi)發(fā)的以太網(wǎng)中的約束,1980年開(kāi)始實(shí)施,并于1983年進(jìn)行了標(biāo)準(zhǔn)化。
最后一個(gè)問(wèn)題:為什么以太網(wǎng)有效載荷大小設(shè)置為1500字節(jié)?沒(méi)有深刻的理由,這只是一個(gè)很好的折衷點(diǎn)。每幀需要42字節(jié)的非有效載荷數(shù)據(jù)。如果有效載荷最大值只有100字節(jié),那么只有70%(100/142)的時(shí)間用于發(fā)送有效載荷。有效載荷為1500字節(jié)意味著大約有97%(1500/1542)的時(shí)間用于發(fā)送有效載荷,這是一個(gè)很好的效率水平。將數(shù)據(jù)包大小提高較多的話,則設(shè)備需要較大的緩沖區(qū),我們還是很難獲得另外高1%或2%的效率。簡(jiǎn)而言之:HTTP / 2的header壓縮是由于20世紀(jì)70年代后期網(wǎng)絡(luò)設(shè)備的RAM限制而導(dǎo)致的。
【程序員應(yīng)該了解的網(wǎng)絡(luò)協(xié)議】相關(guān)文章:
網(wǎng)絡(luò)不通應(yīng)該如何檢查01-10
一級(jí)建造師你應(yīng)該了解的常識(shí)06-28
中高級(jí)PHP程序員應(yīng)該掌握哪些技術(shù)03-31
應(yīng)該如何做明確目標(biāo)java程序員職業(yè)規(guī)劃07-24
網(wǎng)絡(luò)直播應(yīng)該保護(hù)未成年人權(quán)益08-25
了解英語(yǔ)短語(yǔ)05-27
了解什么是編程語(yǔ)言04-05
了解身邊的“歷史”教案04-22
高考政策信息了解02-26