IP 協(xié)議
IP 協(xié)議全稱(chēng)為 “網(wǎng)際互連協(xié)議(Internet Protocol)”,IP 協(xié)議是 TCP/IP 體系中的網(wǎng)絡(luò)層協(xié)議。
基本概念
網(wǎng)絡(luò)層解決的問(wèn)題
TCP 作為傳輸層控制協(xié)議,其保證的是數(shù)據(jù)傳輸?shù)目煽啃院蛡鬏斝?,?TCP 提供的僅僅是數(shù)據(jù)傳輸?shù)牟呗?,而真正?fù)責(zé)數(shù)據(jù)在網(wǎng)絡(luò)中傳輸?shù)膭t傳輸層之下的網(wǎng)絡(luò)層和鏈路層。
雙方在進(jìn)行網(wǎng)絡(luò)通信時(shí),發(fā)送的數(shù)據(jù)并不是直接從一方的傳輸層直接發(fā)送到了另一方的傳輸層,而是需要傳輸層將數(shù)據(jù)繼續(xù)向下進(jìn)行交付,在網(wǎng)絡(luò)層和鏈路層經(jīng)過(guò)數(shù)據(jù)封裝后再通過(guò)網(wǎng)絡(luò)發(fā)送到對(duì)方主機(jī),對(duì)方主機(jī)收到數(shù)據(jù)后也同樣需要在鏈路層和網(wǎng)絡(luò)層進(jìn)行數(shù)據(jù)解包,此時(shí)對(duì)方的傳輸層才拿到了發(fā)送過(guò)來(lái)的數(shù)據(jù),然后再繼續(xù)將該數(shù)據(jù)向上進(jìn)行交付。
網(wǎng)絡(luò)通信的過(guò)程,就像兩個(gè)人在送互相送數(shù)據(jù),這兩個(gè)人分別在兩棟樓的四樓,如果一個(gè)人要將數(shù)據(jù)交給對(duì)方,那么這個(gè)人就必須先從四樓走到一樓,然后再在路上經(jīng)過(guò)路徑選擇到達(dá)對(duì)方樓下,最后再上到四樓將數(shù)據(jù)交給對(duì)方。
其中,送數(shù)據(jù)的這個(gè)人從四樓下來(lái)的過(guò)程就是數(shù)據(jù)封裝的過(guò)程,這個(gè)人在路上經(jīng)過(guò)路徑選擇到達(dá)對(duì)方樓下的過(guò)程就是數(shù)據(jù)路由的過(guò)程,而這個(gè)人再上到四樓將數(shù)據(jù)交給對(duì)方的過(guò)程就是數(shù)據(jù)解包的過(guò)程。
而網(wǎng)絡(luò)層要解決的問(wèn)題就是,將數(shù)據(jù)從一臺(tái)主機(jī)送到另一臺(tái)主機(jī),也就是數(shù)據(jù)的路由。
保證數(shù)據(jù)可靠的從一臺(tái)主機(jī)送到另一臺(tái)主機(jī)的前提
當(dāng)雙方在進(jìn)行基于 TCP 的網(wǎng)絡(luò)通信時(shí),要保證將數(shù)據(jù)可靠的從一臺(tái)主機(jī)送到另一臺(tái)主機(jī),前提是發(fā)送方要有將數(shù)據(jù)送到對(duì)方主機(jī)的能力,要是發(fā)送方連將數(shù)據(jù)發(fā)送給對(duì)方的能力都沒(méi)有,那就更不用談可靠的將數(shù)據(jù)送給對(duì)方主機(jī)了。
需要注意的是,發(fā)送方有將數(shù)據(jù)送到對(duì)方主機(jī)的能力,并不意味著發(fā)送方每次發(fā)送的數(shù)據(jù)都能夠成功的發(fā)送到對(duì)方,但如果發(fā)送方連將數(shù)據(jù)發(fā)送給對(duì)方的能力都沒(méi)有,那發(fā)送方基本就不可能將數(shù)據(jù)發(fā)送給對(duì)方。
一旦發(fā)送方有了將數(shù)據(jù)發(fā)送給對(duì)方的能力,就算發(fā)送方某次發(fā)送的數(shù)據(jù)沒(méi)有成功到達(dá)對(duì)方,此時(shí)上層 TCP 由于沒(méi)有收到對(duì)應(yīng)數(shù)據(jù)的應(yīng)答,此時(shí)上層 TCP 會(huì)要求進(jìn)行數(shù)據(jù)重發(fā),直到數(shù)據(jù)成功發(fā)送到對(duì)方主機(jī)為止。
也就是說(shuō),在網(wǎng)絡(luò)層有能力將數(shù)據(jù)送到對(duì)方主機(jī)的情況下,雖然網(wǎng)絡(luò)層不能保證每次都能將數(shù)據(jù)成功送到對(duì)方主機(jī),但在 TCP 提供的可靠性策略的保證下,最終網(wǎng)絡(luò)層就一定能夠?qū)?shù)據(jù)可靠的發(fā)送到對(duì)方主機(jī)。
說(shuō)明一下:
網(wǎng)絡(luò)層解決的問(wèn)題是,將數(shù)據(jù)從一臺(tái)主機(jī)送到另一臺(tái)主機(jī),因此網(wǎng)絡(luò)層解決的是主機(jī)到主機(jī)的問(wèn)題。
一方傳輸層從上方進(jìn)程拿到數(shù)據(jù)后,該數(shù)據(jù)貫穿網(wǎng)絡(luò)協(xié)議棧進(jìn)行封裝和解包,最終到達(dá)對(duì)方傳輸層,此時(shí)對(duì)方傳輸層也會(huì)將數(shù)據(jù)向上交給對(duì)應(yīng)的進(jìn)程,因此傳輸層解決的是進(jìn)程到進(jìn)程的問(wèn)題。
路徑選擇
數(shù)據(jù)進(jìn)行的網(wǎng)絡(luò)傳輸一般都是跨網(wǎng)絡(luò)的,而路由器就是連接多個(gè)網(wǎng)絡(luò)的硬件設(shè)備,因此數(shù)據(jù)在進(jìn)行跨網(wǎng)絡(luò)傳輸時(shí)一定需要經(jīng)過(guò)多個(gè)路由器。
數(shù)據(jù)路由就像我們旅游一樣,當(dāng)確定了要到達(dá)的目標(biāo)主機(jī)后,就需要尋找最短的路徑到達(dá)該目的地。
目的地的確定是非常重要的,因?yàn)槟康牡刂苯記Q定了數(shù)據(jù)路由時(shí)的路徑選擇,這也是跨網(wǎng)絡(luò)找到目標(biāo)主機(jī)的根本。
只有數(shù)據(jù)經(jīng)過(guò)了較為正確的路徑選擇,最終才可能慢慢趨近于目標(biāo)網(wǎng)絡(luò)或目標(biāo)主機(jī)。
確定數(shù)據(jù)路由的目的地后,數(shù)據(jù)就可以在網(wǎng)絡(luò)中進(jìn)行路由了,但數(shù)據(jù)在路由時(shí)無(wú)法自行進(jìn)行路徑選擇,因?yàn)檫@個(gè)數(shù)據(jù)本身是 “不認(rèn)識(shí)路” 的,因此數(shù)據(jù)在路由的過(guò)程中需要不斷 “找路人問(wèn)路”,而這里所謂的“路人” 就是網(wǎng)絡(luò)當(dāng)中的一臺(tái)臺(tái)路由器。
網(wǎng)絡(luò)當(dāng)中的路由器是 “認(rèn)識(shí)路的”,它們將自己的“認(rèn)路經(jīng)驗(yàn)” 都記錄到路由表當(dāng)中,因此路由器可以通過(guò)查路由表找到去特定點(diǎn)的最短路徑。因此數(shù)據(jù)在路由時(shí),會(huì)不斷通過(guò)路由器來(lái)進(jìn)行路徑選擇,以此來(lái)一步步靠近目標(biāo)網(wǎng)絡(luò)或目標(biāo)主機(jī)。
主機(jī)和路由器
主機(jī):配有 IP 地址,但是不進(jìn)行路由控制的設(shè)備。但實(shí)際現(xiàn)在幾乎不存在不進(jìn)行路由控制的設(shè)備了,就連你的筆記本也會(huì)進(jìn)行路由控制。
路由器:既配有 IP 地址,又能進(jìn)行路由控制。實(shí)際現(xiàn)在主流的路由器已經(jīng)不僅僅具有路由的功能了,它甚至具備某些應(yīng)用層的功能。
節(jié)點(diǎn):主機(jī)和路由器的統(tǒng)稱(chēng)。
IP 協(xié)議格式
IP 協(xié)議格式如下:
4 位版本號(hào)(version):指定 IP 協(xié)議的版本(IPv4/IPv6),對(duì)于 IPv4 來(lái)說(shuō),就是 4。
4 位首部長(zhǎng)度(header length):表示 IP 報(bào)頭的長(zhǎng)度,以 4 字節(jié)為單位。
8 位服務(wù)類(lèi)型(Type Of Service):3 位優(yōu)先權(quán)字段(已經(jīng)棄用),4 位 TOS 字段,和 1 位保留字段(必須置為 0)。4 位 TOS 分別表示:最小延時(shí),最大吞吐量,最高可靠性,最小成本。這四者相互沖突,只能選擇一個(gè)。比如對(duì)于 ssh/telnet 這樣的應(yīng)用程序,最小延時(shí)比較重要,而對(duì)于 ftp 這樣的程序,最大吞吐量比較重要。
16 位總長(zhǎng)度(total length):IP 報(bào)文(IP 報(bào)頭 + 有效載荷)的總長(zhǎng)度,用于將各個(gè) IP 報(bào)文進(jìn)行分離。
16 位標(biāo)識(shí)(id):唯一的標(biāo)識(shí)主機(jī)發(fā)送的報(bào)文,如果數(shù)據(jù)在 IP 層進(jìn)行了分片,那么每一個(gè)分片對(duì)應(yīng)的 id 都是相同的。
3 位標(biāo)志字段:第一位保留,表示暫時(shí)沒(méi)有規(guī)定該字段的意義。第二位表示禁止分片,表示如果報(bào)文長(zhǎng)度超過(guò) MTU,IP 模塊就會(huì)丟棄該報(bào)文。第三位表示 “更多分片”,如果報(bào)文沒(méi)有進(jìn)行分片,則該字段設(shè)置為 0,如果報(bào)文進(jìn)行了分片,則除了最后一個(gè)分片報(bào)文設(shè)置為 0 以外,其余分片報(bào)文均設(shè)置為 1。
13 位片偏移(framegament offset):分片相對(duì)于原始數(shù)據(jù)開(kāi)始處的偏移,表示當(dāng)前分片在原數(shù)據(jù)中的偏移位置,實(shí)際偏移的字節(jié)數(shù)是這個(gè)值× 8 \times 8×8 得到的。因此除了最后一個(gè)報(bào)文之外,其他報(bào)文的長(zhǎng)度必須是 8 的整數(shù)倍,否則報(bào)文就不連續(xù)了。
8 位生存時(shí)間(Time To Live,TTL):數(shù)據(jù)報(bào)到達(dá)目的地的最大報(bào)文跳數(shù),一般是 64,每經(jīng)過(guò)一個(gè)路由,TTL -= 1,一直減到 0 還沒(méi)到達(dá),那么就丟棄了,這個(gè)字段主要是用來(lái)防止出現(xiàn)路由循環(huán)。
8 位協(xié)議:表示上層協(xié)議的類(lèi)型。
16 位首部檢驗(yàn)和:使用 CRC 進(jìn)行校驗(yàn),來(lái)鑒別數(shù)據(jù)報(bào)的首部是否損壞,但不檢驗(yàn)數(shù)據(jù)部分。
32 位源 IP 地址和 32 位目的 IP 地址:表示發(fā)送端和接收端所對(duì)應(yīng)的 IP 地址。
選項(xiàng)字段:不定長(zhǎng),最多 40 字節(jié)。
IP 報(bào)頭在內(nèi)核當(dāng)中本質(zhì)就是一個(gè)位段類(lèi)型,給數(shù)據(jù)封裝 IP 報(bào)頭時(shí),實(shí)際上就是用該位段類(lèi)型定義一個(gè)變量,然后填充 IP 報(bào)頭當(dāng)中的各個(gè)屬性字段,最后將這個(gè) IP 報(bào)頭拷貝到數(shù)據(jù)的首部,至此便完成了 IP 報(bào)頭的封裝。
IP 如何將報(bào)頭與有效載荷進(jìn)行分離?
IP 分離報(bào)頭與有效載荷的方法與 TCP 是一模一樣的,當(dāng) IP 從底層獲取到一個(gè)報(bào)文后,雖然 IP 不知道報(bào)頭的具體長(zhǎng)度,但 IP 報(bào)文的前 20 個(gè)字節(jié)是 IP 的基本報(bào)頭,并且這 20 字節(jié)當(dāng)中涵蓋 4 位首部長(zhǎng)度。
因此 IP 是這樣分離報(bào)頭與有效載荷的:
當(dāng) IP 從底層獲取到一個(gè)報(bào)文后,首先讀取報(bào)文的前 20 個(gè)字節(jié),并從中提取出 4 位的首部長(zhǎng)度,此時(shí)便獲得了 IP 報(bào)頭的大小s i z e sizesize。
如果s i z e sizesize 的值大于 20 字節(jié),則需要繼續(xù)從報(bào)文當(dāng)中讀取s i z e − 20 size-20size−20 字節(jié)的數(shù)據(jù),這部分?jǐn)?shù)據(jù)就是 IP 報(bào)頭當(dāng)中的選項(xiàng)字段。
讀取完 IP 的基本報(bào)頭和選項(xiàng)字段后,剩下的就是有效載荷了。
IP 就是通過(guò)這種 “定長(zhǎng)報(bào)頭 + 自描述字段” 的方式進(jìn)行報(bào)頭和有效載荷的分離的。但需要注意的是,IP 報(bào)頭當(dāng)中的 4 位首部長(zhǎng)度描述的基本單位與 TCP 報(bào)頭當(dāng)中的 4 位首部長(zhǎng)度一樣,都是以 4 字節(jié)為單位進(jìn)行描述的,這也恰好是報(bào)文的寬度。
4 位二進(jìn)制的取值范圍是 0000 ~ 1111,因此 IP 報(bào)頭的最大長(zhǎng)度為15 × 4 = 60 15\times 4=6015×4=60 字節(jié),因?yàn)榛緢?bào)頭的長(zhǎng)度是 20 字節(jié),所以 IP 報(bào)頭中選項(xiàng)字段的長(zhǎng)度最多是 40 字節(jié)。如果 IP 報(bào)頭當(dāng)中不攜帶選項(xiàng)字段,那么 IP 報(bào)頭的長(zhǎng)度就是 20 字節(jié),此時(shí)報(bào)頭當(dāng)中的 4 位首部長(zhǎng)度字段所填的值就是20 ÷ 4 = 5 20\div 4=520÷4=5,即 0101。
IP 如何決定將有效載荷交付給上層的哪一個(gè)協(xié)議?
基于 IP 協(xié)議的傳輸層協(xié)議不止一種,因此當(dāng) IP 從底層獲取到一個(gè)報(bào)文并對(duì)其進(jìn)行解包后,IP 需要知道應(yīng)該將分離后得到的有效載荷交付給上層的哪一個(gè)協(xié)議。
在 IP 報(bào)頭當(dāng)中有一個(gè)字段叫做 8 位協(xié)議,該字段表示的就是上層協(xié)議的類(lèi)型,IP 就是根據(jù)該字段判定應(yīng)該將分離出來(lái)的有效載荷交付給上層的哪一個(gè)協(xié)議的。該字段是發(fā)送方的 IP 層從上層傳輸層獲取到數(shù)據(jù)后填充的,比如是上層 TCP 交給 IP 層的數(shù)據(jù),那么該數(shù)據(jù)在封裝 IP 報(bào)頭時(shí)的 8 位協(xié)議填充的就是 TCP 對(duì)應(yīng)的編號(hào)。
32 位源 IP 地址和 32 位目的 IP 地址
IP 報(bào)頭當(dāng)中的 32 位源 IP 地址和 32 位目的 IP 地址,分別代表的就是該報(bào)文的發(fā)送端和接收端對(duì)應(yīng)的 IP 地址。
數(shù)據(jù)在網(wǎng)絡(luò)傳輸過(guò)程中會(huì)遇到一個(gè)個(gè)的路由器,這些路由器會(huì)幫助網(wǎng)絡(luò)當(dāng)中的數(shù)據(jù)進(jìn)行路由轉(zhuǎn)發(fā),使得網(wǎng)絡(luò)中的數(shù)據(jù)慢慢趨近于目標(biāo)主機(jī)。路由器在幫助數(shù)據(jù)進(jìn)行路由轉(zhuǎn)發(fā)時(shí),會(huì)提取出該數(shù)據(jù)的 IP 報(bào)頭當(dāng)中的目的 IP 地址,并以此作為數(shù)據(jù)路由轉(zhuǎn)發(fā)的重要依據(jù)。
當(dāng)接收端收到了發(fā)送端發(fā)來(lái)的數(shù)據(jù)后,接收端可能也想要給發(fā)送端發(fā)送數(shù)據(jù),因此發(fā)送端在發(fā)送數(shù)據(jù)時(shí)除了需要指明該數(shù)據(jù)的目的 IP 地址,還需要指明該數(shù)據(jù)的源 IP 地址,也就是發(fā)送端的 IP 地址。即便接收端收到數(shù)據(jù)后沒(méi)有數(shù)據(jù)想要發(fā)送給發(fā)送端,但至少接收端需要向發(fā)送端發(fā)送一個(gè)響應(yīng)報(bào)文,表明發(fā)送端發(fā)送的數(shù)據(jù)已經(jīng)被接收端可靠的收到了,因此發(fā)送出去的數(shù)據(jù)除了需要指明該數(shù)據(jù)的目的 IP 地址,還需要指明該數(shù)據(jù)的源 IP 地址。
理解 socket 編程:
在進(jìn)行 socket 編程的時(shí)候,當(dāng)一端想要發(fā)送數(shù)據(jù)給另一端時(shí),必須要指明對(duì)端的 IP 地址和端口號(hào),也就是發(fā)送數(shù)據(jù)的目的 IP 地址和目的端口號(hào)。
其中這里的 IP 地址就是給網(wǎng)絡(luò)層的 IP 用的,用于數(shù)據(jù)在網(wǎng)絡(luò)傳輸過(guò)程中的路由轉(zhuǎn)發(fā),而這里的端口號(hào)就是給傳輸層的 TCP 或 UDP 用的,用于指明該數(shù)據(jù)應(yīng)該交給上層的哪一個(gè)進(jìn)程。
發(fā)送數(shù)據(jù)時(shí)我們不需要指明發(fā)送數(shù)據(jù)的源 IP 地址和源端口號(hào),因?yàn)閭鬏攲雍途W(wǎng)絡(luò)層都是在操作系統(tǒng)內(nèi)核當(dāng)中實(shí)現(xiàn)的,數(shù)據(jù)在進(jìn)行封裝時(shí)操作系統(tǒng)會(huì)自行填充上對(duì)應(yīng)的源 IP 地址和源端口號(hào)。
8 位生存時(shí)間
報(bào)文在網(wǎng)絡(luò)傳輸過(guò)程中,可能因?yàn)槟承┰驅(qū)е聢?bào)文無(wú)法到達(dá)目標(biāo)主機(jī),比如報(bào)文在路由時(shí)出現(xiàn)了環(huán)路路由的情況,或者目標(biāo)主機(jī)已經(jīng)異常離線(xiàn)了,此時(shí)這個(gè)報(bào)文就成了一個(gè)廢棄的游離報(bào)文。
為了避免網(wǎng)絡(luò)當(dāng)中出現(xiàn)大量的游離報(bào)文,于是在 IP 的報(bào)頭當(dāng)中就出現(xiàn)了一個(gè)字段,叫做 8 位生存時(shí)間(Time To Live,TTL)。8 位生存時(shí)間代表的是報(bào)文到達(dá)目的地的最大報(bào)文跳數(shù),每當(dāng)報(bào)文經(jīng)過(guò)一次路由,這里的生存時(shí)間就會(huì)減一,當(dāng)生存時(shí)間減為 0 時(shí)該報(bào)文就會(huì)被自動(dòng)丟棄,此時(shí)這個(gè)報(bào)文就會(huì)在網(wǎng)絡(luò)中消散。
分片與組裝
數(shù)據(jù)鏈路層解決的問(wèn)題
IP 能夠?qū)?shù)據(jù)跨網(wǎng)絡(luò)從一臺(tái)主機(jī)送到另一臺(tái)主機(jī),而數(shù)據(jù)在進(jìn)行跨網(wǎng)絡(luò)傳送時(shí),需要經(jīng)過(guò)一個(gè)個(gè)的路由器進(jìn)行路由轉(zhuǎn)發(fā),最終才能到達(dá)目標(biāo)主機(jī)。
比如要將數(shù)據(jù)從主機(jī) B 跨網(wǎng)絡(luò)傳送到主機(jī) C,那么主機(jī) B 需要先將數(shù)據(jù)交給路由器 F,路由器 F 再將數(shù)據(jù)交給路由器 G,…,最終由路由器 D 將數(shù)據(jù)交給主機(jī) C。
因此 IP 進(jìn)行數(shù)據(jù)跨網(wǎng)絡(luò)傳送的前提是,需要先將數(shù)據(jù)從一個(gè)節(jié)點(diǎn)傳送到和自己相連的下一個(gè)節(jié)點(diǎn),這個(gè)問(wèn)題實(shí)際就是由 IP 之下的數(shù)據(jù)鏈路層解決的,其中數(shù)據(jù)鏈路層最典型的代表協(xié)議就是 MAC 幀。
而兩個(gè)節(jié)點(diǎn)直接相連也就意味著這兩個(gè)節(jié)點(diǎn)是在同一個(gè)局域網(wǎng)當(dāng)中的,因此要討論兩個(gè)相鄰節(jié)點(diǎn)的數(shù)據(jù)傳送時(shí),實(shí)際討論的就是局域網(wǎng)通信的問(wèn)題。
最大傳輸單元 MTU
MAC 幀作為數(shù)據(jù)鏈路層的協(xié)議,它會(huì)將 IP 傳下來(lái)的數(shù)據(jù)封裝成數(shù)據(jù)幀,然后發(fā)送到網(wǎng)絡(luò)當(dāng)中。但 MAC 幀攜帶的有效載荷的最大長(zhǎng)度是有限制的,也就是說(shuō) IP 交給 MAC 幀的報(bào)文不能超過(guò)某個(gè)值,這個(gè)值就叫做最大傳輸單元(Maximum Transmission Unit,MTU),這個(gè)值的大小一般是 1500 字節(jié)。
在 Linux 下使用ifconfig命令可以查看對(duì)應(yīng)的 MTU。
由于 MAC 幀無(wú)法發(fā)送大于 1500 字節(jié)的數(shù)據(jù),因此 IP 層向下交付的數(shù)據(jù)的長(zhǎng)度不能超過(guò) 1500 字節(jié),這里所說(shuō)的數(shù)據(jù)包括 IP 的報(bào)頭和 IP 的有效載荷。
分片與組裝
如果 IP 層要傳送的數(shù)據(jù)超過(guò)了 1500 字節(jié),那么就需要先在 IP 層對(duì)該數(shù)據(jù)進(jìn)行分片,然后再將分片后的數(shù)據(jù)交給下層 MAC 幀進(jìn)行發(fā)送。
如果發(fā)送數(shù)據(jù)時(shí)在 IP 層進(jìn)行了分片,那么當(dāng)這些分片數(shù)據(jù)到達(dá)對(duì)端主機(jī)的 IP 層后就需要先進(jìn)行組裝,然后再將組裝好的數(shù)據(jù)交付給上層傳輸層。
注意:
數(shù)據(jù)的分片不是經(jīng)常需要做的,實(shí)際在網(wǎng)絡(luò)通信過(guò)程中不分片才是常態(tài),因?yàn)閿?shù)據(jù)分片會(huì)存在一些潛在的問(wèn)題,比如分片可能會(huì)增加丟包的概率。
數(shù)據(jù)的分片和組裝發(fā)生在 IP 層,不僅源端主機(jī)可能會(huì)對(duì)數(shù)據(jù)進(jìn)行分片,數(shù)據(jù)在路由過(guò)程中的路由器也可能對(duì)數(shù)據(jù)進(jìn)行分片。因?yàn)椴煌W(wǎng)絡(luò)的 MTU 是不一樣的,如果傳輸路徑上的某個(gè)網(wǎng)絡(luò)的 MTU 比源端網(wǎng)絡(luò)的 MTU 小,那么路由器就可能對(duì) IP 數(shù)據(jù)報(bào)再次進(jìn)行分片。
分片數(shù)據(jù)的組裝只會(huì)發(fā)生在目的端的 IP 層。
在分片的數(shù)據(jù)中,每一個(gè)分片在 IP 層都會(huì)被添加上對(duì)應(yīng)的 IP 報(bào)頭,而傳輸層添加的報(bào)頭只會(huì)出現(xiàn)在第一個(gè)分片中,因此網(wǎng)絡(luò)中傳輸?shù)臄?shù)據(jù)包可能沒(méi)有傳輸層的報(bào)頭。
數(shù)據(jù)的分片和組裝都是由 IP 層完成的
數(shù)據(jù)的分片和組裝都是在 IP 層完成的,上層的傳輸層和下層的鏈路層并不關(guān)心。
傳輸層只負(fù)責(zé)為數(shù)據(jù)傳送提供可靠性保證,比如當(dāng)數(shù)據(jù)傳送失敗后,傳輸層的 TCP 協(xié)議可以組織進(jìn)行數(shù)據(jù)重傳。
當(dāng) TCP 將待發(fā)送的數(shù)據(jù)交給 IP 后,TCP 并不關(guān)心該數(shù)據(jù)是否會(huì)在 IP 層進(jìn)行分片,即 TCP 并不關(guān)心數(shù)據(jù)具體的發(fā)送過(guò)程。
當(dāng) TCP 從 IP 獲取到數(shù)據(jù)后,TCP 也不關(guān)心該數(shù)據(jù)是否在 IP 層經(jīng)過(guò)了組裝。而鏈路層的 MAC 幀只負(fù)責(zé),將數(shù)據(jù)從一個(gè)節(jié)點(diǎn)傳送到和自己相連的下一個(gè)節(jié)點(diǎn)。
當(dāng) IP 將待發(fā)送的數(shù)據(jù)交給 MAC 幀后,MAC 幀并不知道該數(shù)據(jù)是 IP 經(jīng)過(guò)分片后的某個(gè)分片數(shù)據(jù),還是一個(gè)沒(méi)有經(jīng)過(guò)分片的數(shù)據(jù),MAC 幀只知道它一次最多只能發(fā)送 MTU 大小的數(shù)據(jù),如果 IP 交給 MAC 幀大于 MTU 字節(jié)的數(shù)據(jù),那 MAC 幀就無(wú)法進(jìn)行發(fā)送。
當(dāng) MAC 幀從網(wǎng)絡(luò)中獲取到數(shù)據(jù)后,MAC 幀也不關(guān)心這個(gè)數(shù)據(jù)是否需要進(jìn)行組裝,MAC 幀只需要將該數(shù)據(jù)的 MAC 幀報(bào)頭去掉后直接上交給上層 IP 就行了,而至于該數(shù)據(jù)的組裝問(wèn)題則是 IP 需要解決的。
因此,數(shù)據(jù)的分片和組裝完全是由 IP 協(xié)議自己完成的,傳輸層和鏈路層不必關(guān)心也不需要關(guān)心。
分片的過(guò)程
假設(shè) IP 層要發(fā)送 4500 字節(jié)的數(shù)據(jù),由于該數(shù)據(jù)超過(guò)了 MAC 幀規(guī)定的 MTU,因此 IP 需要先將該數(shù)據(jù)進(jìn)行分片,然后再將一個(gè)個(gè)的分片交給 MAC 幀進(jìn)行發(fā)送。
IP 報(bào)頭如果不攜帶選項(xiàng)字段,那么其大小就是 20 字節(jié),假設(shè) IP 層添加的 IP 報(bào)頭的長(zhǎng)度就是 20 字節(jié),并按下列方式將數(shù)據(jù)分片后形成了四個(gè)分片報(bào)文:
需要注意的是,分片后的每一個(gè)分片數(shù)據(jù)都需要封裝上對(duì)應(yīng)的 IP 報(bào)頭,因此 4500 字節(jié)的數(shù)據(jù)至少需要分為四個(gè)分片報(bào)文進(jìn)行發(fā)送。
分片報(bào)文到達(dá)對(duì)方的 IP 層后需要被重新組裝起來(lái),因此 IP 層在對(duì)數(shù)據(jù)進(jìn)行分片時(shí)需要記錄分片的信息,而 IP 報(bào)頭當(dāng)中的 16 位標(biāo)識(shí)、3 位標(biāo)志和 13 位片偏移實(shí)際就是與數(shù)據(jù)分片相關(guān)的字段。
16 位標(biāo)識(shí):唯一標(biāo)識(shí)主機(jī)發(fā)送的報(bào)文,如果數(shù)據(jù)在 IP 層進(jìn)行了分片,那么每一個(gè)分片報(bào)文的 16 位標(biāo)識(shí)是相同的。
3 位標(biāo)志:第一位保留,表示暫時(shí)沒(méi)有規(guī)定該字段的意義。第二位表示禁止分片,表示如果報(bào)文長(zhǎng)度超過(guò) MTU,IP 模塊就會(huì)丟棄該報(bào)文。第三位表示 “更多分片”,如果報(bào)文沒(méi)有進(jìn)行分片,則該字段設(shè)置為 0,如果報(bào)文進(jìn)行了分片,則除了最后一個(gè)分片報(bào)文設(shè)置為 0 以外,其余分片報(bào)文均設(shè)置為 1。
13 位片偏移:分片相對(duì)于原始數(shù)據(jù)開(kāi)始處的偏移,表示當(dāng)前分片在原數(shù)據(jù)中的偏移位置,實(shí)際偏移的字節(jié)數(shù)是這個(gè)值× 8 \times 8×8 得到的。因此除了最后一個(gè)報(bào)文之外,其他報(bào)文的長(zhǎng)度必須是 8 的整數(shù)倍,否則報(bào)文就不連續(xù)了。
因此上述四個(gè)分片報(bào)文對(duì)應(yīng)的 16 位標(biāo)識(shí)都是一樣的,假設(shè)四個(gè)分片報(bào)文的 16 位標(biāo)識(shí)都是 123,則這四個(gè)報(bào)文對(duì)應(yīng)的 16 位標(biāo)識(shí)、3 位標(biāo)志中的 “更多分片” 和 13 位片偏移分別如下:
需要注意的是,13 位片偏移當(dāng)中記錄的字節(jié)數(shù)是當(dāng)前分片在原數(shù)據(jù)開(kāi)始處的偏移字節(jié)數(shù)的值÷ 8 \div 8÷8 得到的,比如分片報(bào)文 2 在原始數(shù)據(jù)開(kāi)始處的偏移字節(jié)數(shù)是 1480,其對(duì)應(yīng)的 13 位片偏移的值就是1480 ÷ 8 = 185 1480\div 8=1851480÷8=185。
組裝的過(guò)程
MAC 幀交給 IP 層的數(shù)據(jù)可能來(lái)自世界各地,這些數(shù)據(jù)可能是經(jīng)過(guò)分片后發(fā)送的,也可能是沒(méi)有經(jīng)過(guò)分片直接發(fā)送的,因此 IP 必須要通過(guò)某種方式來(lái)區(qū)分收到的各個(gè)數(shù)據(jù)。
IP 報(bào)頭當(dāng)中有 32 位源 IP 地址,源 IP 地址記錄了發(fā)送端所對(duì)應(yīng)的 IP 地址,因此通過(guò) IP 報(bào)頭當(dāng)中的 32 位源 IP 地址就可以區(qū)分來(lái)自不同主機(jī)的數(shù)據(jù)。
IP 報(bào)頭當(dāng)中有 16 位標(biāo)識(shí),未分片的數(shù)據(jù)各自的 16 位標(biāo)識(shí)都是不同的,而由同一個(gè)數(shù)據(jù)分片得到的各個(gè)分片報(bào)文所對(duì)應(yīng)的 16 位標(biāo)識(shí)都是相同的,因此通過(guò) IP 報(bào)頭當(dāng)中 16 位標(biāo)識(shí)就可以判斷哪些報(bào)文是沒(méi)有經(jīng)過(guò)分片的獨(dú)立報(bào)文,哪些報(bào)文是經(jīng)過(guò)分片后的分片報(bào)文。因此 IP 可以通過(guò) IP 報(bào)頭當(dāng)中的 32 位源 IP 地址和 16 位標(biāo)識(shí),將經(jīng)過(guò)分片的數(shù)據(jù)各自聚合在一起,聚合在一起后就可以開(kāi)始進(jìn)行組裝了。
對(duì)于各個(gè)分片報(bào)文來(lái)說(shuō):
第一個(gè)分片報(bào)文中的 13 位片偏移的值一定為 0。
最后一個(gè)分片報(bào)文中的 “更多分片” 標(biāo)志位一定為 0。
對(duì)于每一個(gè)分片報(bào)文來(lái)說(shuō),當(dāng)前報(bào)文的 13 位片偏移加上當(dāng)前報(bào)文的數(shù)據(jù)字節(jié)數(shù) ÷ \div÷ 8 所得到的值,就是下一個(gè)分片報(bào)文的所對(duì)應(yīng)的 13 位片偏移。
根據(jù)分片報(bào)文的這三個(gè)特點(diǎn)就能夠?qū)⒎制瑘?bào)文合理的組裝起來(lái)。
先找到分片報(bào)文中 13 位片偏移為 0 的分片報(bào)文,然后提取出其 IP 報(bào)頭當(dāng)中的 16 位總長(zhǎng)度字段,通過(guò)計(jì)算即可得出下一個(gè)分片報(bào)文所對(duì)應(yīng)的 13 位片偏移,按照此方式依次將各個(gè)分片報(bào)文拼接起來(lái)。
直到拼接到一個(gè) “更多分片” 標(biāo)志位為 0 的分片報(bào)文,此時(shí)表明分片報(bào)文組裝完畢。
分片報(bào)文丟包的問(wèn)題
分片后的報(bào)文在網(wǎng)絡(luò)傳輸過(guò)程中也可能會(huì)出現(xiàn)丟包問(wèn)題,但接收端有能力判斷是否收到了全部分片報(bào)文,比如假設(shè)某組分片報(bào)文對(duì)應(yīng)的 16 位標(biāo)識(shí)值為 x:
如果分片報(bào)文中的第一個(gè)分片報(bào)文丟包了,那么接收端收到的分片報(bào)文中就找不到對(duì)應(yīng) 16 位標(biāo)識(shí)為 x,并且 13 位片偏移為 0 的分片報(bào)文。
如果分片報(bào)文中的最后一個(gè)分片報(bào)文丟包了,那么接收端收到的分片報(bào)文中就找不到對(duì)應(yīng) 16 為標(biāo)識(shí)為 x,并且 “更多分片” 標(biāo)志位為 0 的分片報(bào)文。
如果分片報(bào)文中的其它分片報(bào)文丟包了,那么接收端在進(jìn)行分片報(bào)文的組裝時(shí)就會(huì)找不到對(duì)應(yīng) 13 位片偏移為特定值的分片報(bào)文。
需要注意的是,未分片報(bào)文的 “更多分片” 標(biāo)志位為 0,最后一個(gè)分片報(bào)文的 “更多分片” 標(biāo)志位也為 0,但當(dāng)接收端只收到分片報(bào)文中的最后一個(gè)分片報(bào)文時(shí),接收端不會(huì)將其識(shí)別成一個(gè)未分片的報(bào)文,因?yàn)槲捶制膱?bào)文所對(duì)應(yīng)的 13 位片偏移的值也應(yīng)該是 0,而最后一個(gè)分片報(bào)文所對(duì)應(yīng)的 13 位片偏移的值不為 0。
因此只有當(dāng)一個(gè)報(bào)文的 13 位片偏移為 0,并且該報(bào)文的 “更多分片” 標(biāo)志位也為 0 時(shí),該報(bào)文才會(huì)被識(shí)別成一個(gè)沒(méi)有被分片的獨(dú)立報(bào)文,否則該報(bào)文就會(huì)被識(shí)別成一個(gè)分片報(bào)文。
為什么不建議進(jìn)行分片?
雖然傳輸層并不關(guān)心 IP 層的分片問(wèn)題,但分片對(duì)傳輸層也是有影響的。
如果一個(gè)數(shù)據(jù)在網(wǎng)絡(luò)傳輸過(guò)程中沒(méi)有經(jīng)過(guò)分片,那么只要接收端收到了這一個(gè)報(bào)文,我們就可以認(rèn)為該數(shù)據(jù)被對(duì)方可靠的收到了。
而如果一個(gè)數(shù)據(jù)在網(wǎng)絡(luò)傳輸過(guò)程中進(jìn)行了分片,那么只有當(dāng)接收端收到了全部的分片報(bào)文并將其成功組裝起來(lái),這時(shí)我們才認(rèn)為該數(shù)據(jù)被對(duì)方可靠的收到了。但如果眾多的分片報(bào)文當(dāng)中有一個(gè)報(bào)文出現(xiàn)了丟包,就會(huì)導(dǎo)致接收端就無(wú)法將報(bào)文成功組裝起來(lái),這時(shí)接收端會(huì)將收到的分片報(bào)文全部丟棄,此時(shí)傳輸層 TCP 會(huì)因?yàn)槭詹坏綄?duì)方應(yīng)答而進(jìn)行超時(shí)重傳。
假設(shè)在網(wǎng)絡(luò)傳輸時(shí)丟包的概率是萬(wàn)分之一,如果將數(shù)據(jù)拆分為一百份進(jìn)行發(fā)送,那么此時(shí)丟包的概率就上升到了百分之一。因?yàn)橹灰幸粋€(gè)分片報(bào)文丟包了也就等同于這個(gè)報(bào)文整體丟失了,因此分片會(huì)增加傳輸層重傳數(shù)據(jù)的概率。
需要注意的是,只要分片報(bào)文當(dāng)中的某一個(gè)出現(xiàn)了丟包,此時(shí)傳輸層都需要將數(shù)據(jù)整體進(jìn)行重傳,因?yàn)閭鬏攲硬⒉恢赖讓?IP 對(duì)數(shù)據(jù)進(jìn)行了分片,當(dāng)傳輸層發(fā)送出去的數(shù)據(jù)得不到應(yīng)答時(shí)傳輸層就只能將數(shù)據(jù)整體進(jìn)行重傳,因此數(shù)據(jù)在發(fā)送時(shí)不建議進(jìn)行分片。
如何盡可能避免分片?
實(shí)際數(shù)據(jù)分片的根本原因在于傳輸層一次向下交付的數(shù)據(jù)太多了,導(dǎo)致 IP 無(wú)法直接將數(shù)據(jù)向下交給 MAC 幀,如果傳輸層控制好一次交給 IP 的數(shù)據(jù)量不要太大,那么數(shù)據(jù)在 IP 層自然也就不需要進(jìn)行分片。
因此 TCP 作為傳輸控制協(xié)議,它需要控制一次向下交付數(shù)據(jù)不能超過(guò)某一閾值,這個(gè)閾值就叫做 MSS(Maximum Segment Size,最大報(bào)文段長(zhǎng)度)。
通信雙方在建立 TCP 連接時(shí),除了需要協(xié)商自身窗口大小等概念之外,還會(huì)協(xié)商后續(xù)通信時(shí)每一個(gè)報(bào)文段所能承載的最大報(bào)文段長(zhǎng)度 MSS。
MAC 幀的有效載荷最大為 MTU,TCP 的有效載荷最大為 MSS,由于 TCP 和 IP 常規(guī)情況下報(bào)頭的長(zhǎng)度都是 20 字節(jié),因此一般情況下 MSS = MTU - 20 - 20,而 MTU 的值一般是 1500 字節(jié),因此 MSS 的值一般就是 1460 字節(jié)。
所以一般建議 TCP 將發(fā)送的數(shù)據(jù)控制在 1460 字節(jié)以?xún)?nèi),此時(shí)就能夠降低數(shù)據(jù)分片的可能性。之所以說(shuō)是降低數(shù)據(jù)分片的可能性,是因?yàn)槊總€(gè)網(wǎng)絡(luò)的鏈路層對(duì)應(yīng)的 MTU 可能是不同的,如果數(shù)據(jù)在傳輸過(guò)程中進(jìn)入到了一個(gè) MTU 較小的網(wǎng)絡(luò),那么該數(shù)據(jù)仍然可能需要在路由器中進(jìn)行分片。
網(wǎng)段劃分
IP 地址的構(gòu)成
IP 地址由網(wǎng)絡(luò)號(hào)和主機(jī)號(hào)兩部分構(gòu)成:
網(wǎng)絡(luò)號(hào):保證相互連接的兩個(gè)網(wǎng)段具有不同的標(biāo)識(shí)。
主機(jī)號(hào):同一網(wǎng)段內(nèi),主機(jī)之間具有相同的網(wǎng)絡(luò)號(hào),但是必須有不同的主機(jī)號(hào)??梢栽?IP 地址的后面加一個(gè) /,并在 / 后面加上一個(gè)數(shù)字,這就表示從頭數(shù)到第幾位為止屬于網(wǎng)絡(luò)標(biāo)識(shí)。
例如,下圖中路由器連接了兩個(gè)網(wǎng)段。對(duì)于網(wǎng)絡(luò)標(biāo)識(shí)來(lái)講,同一網(wǎng)段內(nèi)主機(jī)的網(wǎng)絡(luò)標(biāo)識(shí)是相同的,不同網(wǎng)段內(nèi)主機(jī)的網(wǎng)絡(luò)標(biāo)識(shí)是不同的。而對(duì)于主機(jī)標(biāo)識(shí)來(lái)講,同一網(wǎng)段內(nèi)主機(jī)的主機(jī)標(biāo)識(shí)是不同的,不同網(wǎng)段內(nèi)主機(jī)的主機(jī)標(biāo)識(shí)是可以相同的。
不同的子網(wǎng)其實(shí)就是把網(wǎng)絡(luò)號(hào)相同的主機(jī)放到一起。
如果在子網(wǎng)中新增一臺(tái)主機(jī),則這臺(tái)主機(jī)的網(wǎng)絡(luò)號(hào)和這個(gè)子網(wǎng)的網(wǎng)絡(luò)號(hào)一致,但是主機(jī)號(hào)必須不能和子網(wǎng)中的其他主機(jī)重復(fù)。
DHCP 協(xié)議
實(shí)際手動(dòng)管理 IP 地址是一個(gè)非常麻煩的事情,當(dāng)子網(wǎng)中新增主機(jī)時(shí)需要給其分配一個(gè) IP 地址,當(dāng)子網(wǎng)當(dāng)中有主機(jī)斷開(kāi)網(wǎng)絡(luò)時(shí)又需要將其 IP 地址進(jìn)行回收,便于分配給后續(xù)新增的主機(jī)使用。
因此對(duì)于 IP 地址的分配和回收一般不會(huì)手動(dòng)進(jìn)行,而是采用 DHCP(Dynamic Host Configuration Protocol,動(dòng)態(tài)主機(jī)配置協(xié)議)技術(shù)。
DHCP 通常被應(yīng)用在大型的局域網(wǎng)環(huán)境中,其主要作用就是集中地址管理、分配 IP 地址,使網(wǎng)絡(luò)環(huán)境中的主機(jī)動(dòng)態(tài)獲得 IP 地址、Gateway 地址、DNS 服務(wù)器地址等信息,并能夠提升地址的使用率。
DHCP 是一個(gè)基于 UDP 的應(yīng)用層協(xié)議,一般的路由器都帶有 DHCP 功能,因此路由器也可以看作一個(gè) DHCP 服務(wù)器。
當(dāng)我們連接 WiFi 時(shí)需要輸入密碼,本質(zhì)就是因?yàn)槁酚善餍枰?yàn)證你的賬號(hào)和密碼,如果驗(yàn)證通過(guò),那么路由器就會(huì)給你動(dòng)態(tài)分配了一個(gè) IP 地址,然后你就可以基于這個(gè) IP 地址進(jìn)行各種上網(wǎng)動(dòng)作了。
先找目標(biāo)網(wǎng)絡(luò),再找目標(biāo)主機(jī)
當(dāng) IP 要將數(shù)據(jù)跨網(wǎng)絡(luò)從一臺(tái)主機(jī)發(fā)送到另一臺(tái)主機(jī)時(shí),其實(shí)不是直接將數(shù)據(jù)發(fā)送到了目標(biāo)主機(jī),而是先將數(shù)據(jù)發(fā)送到目標(biāo)主機(jī)所在的網(wǎng)絡(luò),然后再將數(shù)據(jù)發(fā)送到目標(biāo)主機(jī)。
因此數(shù)據(jù)在路由時(shí)的第一目的并不是找到目標(biāo)主機(jī),而是找到目標(biāo)網(wǎng)絡(luò)所在的網(wǎng)絡(luò),然后再在目標(biāo)網(wǎng)絡(luò)當(dāng)中找到目標(biāo)主機(jī)。
數(shù)據(jù)路由時(shí)之所以不一開(kāi)始就以找目標(biāo)主機(jī)為目的,因?yàn)檫@樣效率太低了。
找主機(jī)的過(guò)程本質(zhì)是排除的過(guò)程,如果一開(kāi)始就以找目標(biāo)主機(jī)為目的,那么在查找的過(guò)程中一次只能排除一個(gè)主機(jī)。
而如果一開(kāi)始先以找目標(biāo)網(wǎng)絡(luò)為目的,那么在查找過(guò)程中就能一次排除大量和目標(biāo)主機(jī)不在同一網(wǎng)段的主機(jī),這樣就可以大大提高檢索的效率。
因此,為了提高數(shù)據(jù)路由的效率,我們對(duì)網(wǎng)絡(luò)進(jìn)行了網(wǎng)段劃分。
網(wǎng)段劃分
過(guò)去曾經(jīng)提出一種劃分網(wǎng)絡(luò)號(hào)和主機(jī)號(hào)的方案,就是把所有 IP 地址分為五類(lèi),如下圖所示:
因此,各類(lèi) IP 地址的取值范圍如下:
A 類(lèi):0.0.0.0 到 127.255.255.255。
B 類(lèi):128.0.0.0 到 191.255.255.255。
C 類(lèi):192.0.0.0 到 223.255.255.255。
D 類(lèi):224.0.0.0 到 239.255.255.255。
E 類(lèi):240.0.0.0 到 247.255.255.255。當(dāng)要判斷一個(gè) IP 地址是屬于哪一類(lèi)時(shí),只需要遍歷 IP 地址的前五個(gè)比特位,第幾個(gè)比特位最先出現(xiàn) 0 值,那么這個(gè) IP 地址對(duì)應(yīng)就屬于 A、B、C、D、E 類(lèi)地址。
子網(wǎng)劃分
但隨著網(wǎng)絡(luò)的飛速發(fā)展,這種劃分方案的局限性很快就顯現(xiàn)出來(lái)了。
比如一些學(xué)校、公司、實(shí)驗(yàn)室等組織想要申請(qǐng)自己的局域網(wǎng),由于 A 類(lèi)地址的網(wǎng)絡(luò)號(hào)只占 7 個(gè)比特位,因此 A 類(lèi)地址可申請(qǐng)的網(wǎng)絡(luò)只有2 7 2^727 個(gè),于是大多數(shù)組織都選擇申請(qǐng) B 類(lèi)地址。
由于 B 類(lèi)地址的主機(jī)號(hào)占 16 個(gè)比特位,因此理論上一個(gè) B 類(lèi)網(wǎng)絡(luò)當(dāng)中允許有 65536 臺(tái)主機(jī)。
但實(shí)際網(wǎng)絡(luò)架設(shè)中,一般不會(huì)存在一個(gè)局域網(wǎng)當(dāng)中有這么多主機(jī)的情況,也就意味著大量的 IP 地址實(shí)際都被浪費(fèi)掉了。
為了避免這種情況,于是又提出了新的劃分方案,稱(chēng)為 CIDR(Classless Interdomain Routing):
在原有的五類(lèi)網(wǎng)絡(luò)的基礎(chǔ)上繼續(xù)進(jìn)行子網(wǎng)劃分,這也就意味著需要借用主機(jī)號(hào)當(dāng)中的若干位來(lái)充當(dāng)網(wǎng)絡(luò)號(hào),此時(shí)為了區(qū)分 IP 地址中的網(wǎng)絡(luò)號(hào)和主機(jī)號(hào),于是引入了子網(wǎng)掩碼(subnet mask)的概念。
每一個(gè)子網(wǎng)都有自己的子網(wǎng)掩碼,子網(wǎng)掩碼實(shí)際就是一個(gè) 32 位的正整數(shù),通常用一串 “0” 來(lái)結(jié)尾。
將 IP 地址與當(dāng)前網(wǎng)絡(luò)的子網(wǎng)掩碼進(jìn)行 “按位與” 操作,就能夠得到當(dāng)前所在網(wǎng)絡(luò)的網(wǎng)絡(luò)號(hào)。
此時(shí)一個(gè)網(wǎng)絡(luò)就被更細(xì)粒度的劃分成了一個(gè)個(gè)更小的子網(wǎng),通過(guò)不斷的子網(wǎng)劃分,子網(wǎng)中 IP 地址對(duì)應(yīng)的主機(jī)號(hào)就越來(lái)越短,因此子網(wǎng)當(dāng)中可用 IP 地址的個(gè)數(shù)也就越來(lái)越少,這也就避免了 IP 地址被大量浪費(fèi)的情況。
比如在某一子網(wǎng)中將 IP 地址的前 24 位作為網(wǎng)絡(luò)號(hào),那么該網(wǎng)絡(luò)對(duì)應(yīng)的子網(wǎng)掩碼的 32 個(gè)比特位中的前 24 位就為 1,剩下的 8 個(gè)比特位為 0,將其用點(diǎn)分十機(jī)制表示就是 255.255.255.0。
假設(shè)該子網(wǎng)當(dāng)中有一臺(tái)主機(jī)對(duì)應(yīng)的 IP 地址是 192.168.128.10,那么將這個(gè) IP 地址與該網(wǎng)絡(luò)對(duì)應(yīng)的子網(wǎng)掩碼進(jìn)行 “按位與” 操作后得到的就是 192.168.128.0,這就是這個(gè)子網(wǎng)對(duì)應(yīng)的網(wǎng)絡(luò)號(hào)。
實(shí)際在用子網(wǎng)掩碼與子網(wǎng)當(dāng)中主機(jī)的 IP 地址進(jìn)行 “按位與” 操作時(shí),本質(zhì)就是保留了主機(jī) IP 地址中前 24 個(gè)比特位的原貌,將剩下的 8 個(gè)比特位的值清 0 了而已,也就是將主機(jī)號(hào)清 0 了,所以 “按位與” 后的結(jié)果就是該網(wǎng)絡(luò)對(duì)應(yīng)的網(wǎng)絡(luò)號(hào)。
需要注意的是,子網(wǎng)劃分不是只能進(jìn)行一次,我們可以在劃分出來(lái)的子網(wǎng)的基礎(chǔ)上繼續(xù)進(jìn)行子網(wǎng)劃分。
因此一個(gè)數(shù)據(jù)在路由的時(shí)候,隨著數(shù)據(jù)不斷路由進(jìn)入更小的子網(wǎng),其網(wǎng)絡(luò)號(hào)的位數(shù)是在不斷變化的,準(zhǔn)確來(lái)說(shuō)其網(wǎng)絡(luò)號(hào)的位數(shù)是在不斷增加的,這也就意味著 IP 地址當(dāng)中的主機(jī)號(hào)的位數(shù)在不斷減少。最終當(dāng)數(shù)據(jù)路由到達(dá)目標(biāo)主機(jī)所在的網(wǎng)絡(luò)時(shí),就可以在該網(wǎng)絡(luò)當(dāng)中找到對(duì)應(yīng)的目標(biāo)主機(jī)并將數(shù)據(jù)交給該主機(jī),此時(shí)該數(shù)據(jù)的路由也就結(jié)束了。
特殊的 IP 地址
并不是所有的 IP 地址都能夠作為主機(jī)的 IP 地址,有些 IP 地址本身就是具有特殊用途的。
將 IP 地址中的主機(jī)地址全部設(shè)為 0,就成為了網(wǎng)絡(luò)號(hào),代表這個(gè)局域網(wǎng)。
將 IP 地址中的主機(jī)地址全部設(shè)為 1,就成為了廣播地址,用于給同一個(gè)鏈路中相互連接的所有主機(jī)發(fā)送數(shù)據(jù)包。
127.* 的 IP 地址用于本機(jī)環(huán)回(loop back)測(cè)試,通常是 127.0.0.1。
也就是說(shuō),IP 地址中主機(jī)號(hào)為全 0 的代表的是當(dāng)前局域網(wǎng)的網(wǎng)絡(luò)號(hào),IP 地址中主機(jī)號(hào)為全 1 的代表的是廣播地址,這兩個(gè) IP 地址都是不能作為主機(jī)的 IP 地址的。因此在某個(gè)局域網(wǎng)中最多能存在的主機(jī)個(gè)數(shù)是 2 主機(jī)號(hào)位數(shù) − 2 2^{主機(jī)號(hào)位數(shù)}-22主機(jī)號(hào)位數(shù)−2。
本機(jī)環(huán)回基本原理
本機(jī)環(huán)回會(huì)將數(shù)據(jù)貫穿網(wǎng)絡(luò)協(xié)議棧,但最終并不會(huì)將數(shù)據(jù)發(fā)送到網(wǎng)絡(luò)當(dāng)中,相當(dāng)于本機(jī)環(huán)回時(shí)不會(huì)將數(shù)據(jù)寫(xiě)到網(wǎng)卡上面。
本機(jī)環(huán)回的目的就是將數(shù)據(jù)自頂向下貫穿協(xié)議棧,進(jìn)行一次數(shù)據(jù)封裝的過(guò)程的過(guò)程,然后再自底向上貫穿協(xié)議棧,進(jìn)行一次數(shù)據(jù)的解包和分用,用于測(cè)試本地的網(wǎng)絡(luò)功能是否正常。
本機(jī)環(huán)回的基本原理:
當(dāng)數(shù)據(jù)到達(dá) IP 層需要繼續(xù)向下交付時(shí),如果是環(huán)回程序,那么 IP 輸出函數(shù)會(huì)將該數(shù)據(jù)放入到 IP 輸入隊(duì)列當(dāng)中,然后再由 IP 輸入函數(shù)讀取上去。
而 IP 輸入函數(shù)將數(shù)據(jù)讀取上去的本應(yīng)該是鏈路層交付上來(lái)的數(shù)據(jù),因此該數(shù)據(jù)后續(xù)就會(huì)被當(dāng)作從網(wǎng)絡(luò)中讀取上來(lái)的數(shù)據(jù)看待,各層協(xié)議會(huì)對(duì)該數(shù)據(jù)依次進(jìn)行解包和分用。
如果不是環(huán)回程序的話(huà),那么接下來(lái)就會(huì)判斷該數(shù)據(jù)對(duì)應(yīng)的目的 IP 地址是否為廣播或多播地址,或者目的 IP 地址是否與本主機(jī)的 IP 地址相同,如果是則也會(huì)將該數(shù)據(jù)放入到 IP 輸入隊(duì)列當(dāng)中,等待 IP 輸入函數(shù)將其讀走。
只有判斷程序不是環(huán)回程序,并且也不是廣播或多播,或發(fā)給本主機(jī)的數(shù)據(jù)后,才會(huì)用 ARP 獲取該數(shù)據(jù)目的主機(jī)的以太網(wǎng)地址并進(jìn)行后續(xù)數(shù)據(jù)發(fā)送的操作。
loopback 設(shè)備:
IP 地址的數(shù)量限制
IP 地址數(shù)量不足問(wèn)題
我們知道,IP 地址(IPv4)是一個(gè) 4 字節(jié) 32 位的正整數(shù),因此一共有2 32 2^{32}232 個(gè) IP 地址,也就是將近 43 億個(gè) IP 地址。但 TCP/IP 協(xié)議規(guī)定,每個(gè)主機(jī)都需要有一個(gè) IP 地址。
現(xiàn)在全世界人口已經(jīng)有 70 多億了,就算有一半的人沒(méi)有智能手機(jī),算下來(lái)也有 30 多億臺(tái)智能手機(jī)需要 IP 地址。
隨著科技的發(fā)展,我們使用的電腦、智能手表、智能冰箱、智能洗衣機(jī)等設(shè)備如果要入網(wǎng)也是需要 IP 地址的。
另外,IP 地址并不是按照主機(jī)臺(tái)數(shù)來(lái)配置的,因此一個(gè)主機(jī)可能需要多個(gè) IP 地址,更別談還有很多組網(wǎng)的路由設(shè)備也需要 IP 地址,以及一些特殊的 IP 地址不能使用的問(wèn)題。所以 43 億個(gè) IP 地址其實(shí)早就不夠用了,因此才提出了 CIDR 的方案對(duì)已經(jīng)劃分好的五類(lèi)網(wǎng)絡(luò)繼續(xù)進(jìn)行子網(wǎng)劃分,其目的就是為了減少 IP 地址的浪費(fèi),根本原因就是 IP 地址本來(lái)就不夠了,所以不能夠再浪費(fèi)了。
CIDR 雖然在一定程度上緩解了 IP 地址不夠用的問(wèn)題,因?yàn)?CIDR 提高了 IP 地址的利用率,減少了浪費(fèi),但 IP 地址的絕對(duì)上限并沒(méi)有增加。
如何解決 IP 地址不足問(wèn)題
解決 IP 地址不足有以下幾種方式:
動(dòng)態(tài)分配 IP 地址:只給接入網(wǎng)絡(luò)的設(shè)備分配 IP 地址,因此同一個(gè) MAC 地址的設(shè)備,每次接入互聯(lián)網(wǎng)中,得到的 IP 地址不一定是相同的,避免了 IP 地址強(qiáng)綁定于某一臺(tái)設(shè)備。
NAT 技術(shù):能夠讓不同局域網(wǎng)當(dāng)中同時(shí)存在兩個(gè)相同的 IP 地址,NAT 技術(shù)不僅能解決 IP 地址不足的問(wèn)題,而且還能夠有效地避免來(lái)自網(wǎng)絡(luò)外部的攻擊,隱藏并保護(hù)網(wǎng)絡(luò)內(nèi)部的計(jì)算機(jī)。
IPv6:IPv6 用 16 字節(jié) 128 位來(lái)表示一個(gè) IP 地址,能夠大大緩解 IP 地址不足的問(wèn)題。但 IPv6 并不是 IPv4 的簡(jiǎn)單升級(jí)版,它們是互不相干的兩個(gè)協(xié)議,彼此并不兼容,因此目前 IPv6 還沒(méi)有普及。
私網(wǎng) IP 地址和公網(wǎng) IP 地址
私網(wǎng) IP 地址的種類(lèi)
如果一個(gè)組織內(nèi)部組建局域網(wǎng),IP 地址只用于局域網(wǎng)內(nèi)的通信,而不直接連到 Internet 上,理論上使用任意的 IP 地址都可以,但是 RFC 1918 規(guī)定了用于組建局域網(wǎng)的私有 IP 地址。
10.*,前 8 位是網(wǎng)絡(luò)號(hào),共 16,777,216 個(gè)地址。
172.16.* 到 172.31.*,前 12 位是網(wǎng)絡(luò)號(hào),共 1,048,576 個(gè)地址。
192.168.*,前 16 位是網(wǎng)絡(luò)號(hào),共 65,536 個(gè)地址。
包含在這個(gè)范圍中的,都稱(chēng)為私網(wǎng) IP,其余的則稱(chēng)為公網(wǎng) IP(或全局 IP)。
我們連接云服務(wù)器時(shí),連接的這個(gè) IP 地址就是云服務(wù)器的公網(wǎng) IP 地址。
我們可以通過(guò)ifconfig命令來(lái)查看我們這臺(tái)機(jī)器的私網(wǎng) IP,其中網(wǎng)絡(luò)接口 lo(loop)代表的是本地環(huán)回,而 eth0 代表的就是我這臺(tái)機(jī)器的網(wǎng)絡(luò)接口,可以看到我的私網(wǎng) IP 地址是 172.21.0.15。
需要注意的是,這里連接云服務(wù)器時(shí)的 IP 地址 49.232.66.206,是云服務(wù)器的公網(wǎng) IP,由于我使用的是騰訊云,因此這里的 172.21.0.15 是我這個(gè)云服務(wù)器在騰訊內(nèi)部的私網(wǎng) IP,可以看到這個(gè) IP 正好在第二種私網(wǎng) IP 范圍內(nèi)。
此外,打開(kāi) Windows 當(dāng)中的 cmd 窗口,通過(guò)ipconfig命令可以看到大量以 192.168 開(kāi)頭的私網(wǎng) IP。
我們?yōu)槭裁匆o運(yùn)營(yíng)商交錢(qián)?
我們享受的是互聯(lián)網(wǎng)公司提供服務(wù),但為什么需要向運(yùn)營(yíng)商交錢(qián)呢?
實(shí)際網(wǎng)絡(luò)通信的基礎(chǔ)設(shè)施都是運(yùn)營(yíng)商搭建的,我們?cè)L問(wèn)服務(wù)器的數(shù)據(jù)并不是直接發(fā)送到了對(duì)應(yīng)的服務(wù)器,而是需要經(jīng)過(guò)運(yùn)營(yíng)商建設(shè)的各種基站以及各種路由器,最終數(shù)據(jù)才能到達(dá)對(duì)應(yīng)的服務(wù)器。
因?yàn)檫\(yùn)營(yíng)商為我們提供了通信的基礎(chǔ)設(shè)施,所以我們交網(wǎng)費(fèi)實(shí)際就相當(dāng)于購(gòu)買(mǎi)入網(wǎng)許可一樣。
沒(méi)有運(yùn)營(yíng)商提供的這些基礎(chǔ)設(shè)施,就不會(huì)誕生所謂的互聯(lián)網(wǎng)公司,因?yàn)榛ヂ?lián)網(wǎng)公司是誕生在網(wǎng)絡(luò)通信基礎(chǔ)之上的。
也就是說(shuō),用戶(hù)上網(wǎng)的數(shù)據(jù)首先必須經(jīng)過(guò)運(yùn)營(yíng)商的相關(guān)網(wǎng)絡(luò)設(shè)備,然后才能發(fā)送到互聯(lián)網(wǎng)公司對(duì)應(yīng)的服務(wù)器。因此所謂的網(wǎng)段劃分、子網(wǎng)劃分等工作實(shí)際都是運(yùn)營(yíng)商做的。
數(shù)據(jù)是如何發(fā)送到服務(wù)器的
路由器是連接兩個(gè)或多個(gè)網(wǎng)絡(luò)的硬件設(shè)備,在路由器上有兩種網(wǎng)絡(luò)接口,分別是 LAN 口和 WAN 口:
LAN 口(Local Area Network):表示連接本地網(wǎng)絡(luò)的端口,主要與家庭網(wǎng)絡(luò)中的交換機(jī)、集線(xiàn)器或 PC 相連。
WAN 口(Wide Area Network):表示連接廣域網(wǎng)的端口,一般指互聯(lián)網(wǎng)。
我們將 LAN 口的 IP 地址叫做 LAN 口 IP,也叫做子網(wǎng) IP,將 WAN 口的 IP 地址叫做 WAN 口 IPO,也叫做外網(wǎng) IP。
我們使用的電腦、家用路由器、運(yùn)營(yíng)商路由器、廣域網(wǎng)以及我們要訪問(wèn)的服務(wù)器之間的關(guān)系大致如下:
不同的路由器,子網(wǎng) IP 其實(shí)都是一樣的(通常都是 192.168.1.1),子網(wǎng)內(nèi)的主機(jī) IP 地址不能重復(fù),但是子網(wǎng)之間的 IP 地址就可以重復(fù)了。
每一個(gè)家用路由器,其實(shí)又作為運(yùn)營(yíng)商路由器的子網(wǎng)中的一個(gè)節(jié)點(diǎn),這樣的運(yùn)營(yíng)商路由器可能會(huì)有很多級(jí),最外層的運(yùn)營(yíng)商路由器的 WAN 口 IP 就是一個(gè)公網(wǎng) IP 了。
如果希望我們自己實(shí)現(xiàn)的服務(wù)器程序,能夠在公網(wǎng)上被訪問(wèn)到,就需要把程序部署在一臺(tái)具有外網(wǎng) IP 的服務(wù)器上,這樣的服務(wù)器可以在阿里云 / 騰訊云上進(jìn)行購(gòu)買(mǎi)。
由于私網(wǎng) IP 不能出現(xiàn)在公網(wǎng)當(dāng)中,因此子網(wǎng)內(nèi)的主機(jī)在和外網(wǎng)進(jìn)行通信時(shí),路由器會(huì)不斷將數(shù)據(jù)包 IP 首部中的源 IP 地址替換成路由器的 WAN 口 IP,這樣逐級(jí)替換,最終數(shù)據(jù)包中的源 IP 地址成為一個(gè)公網(wǎng) IP,這種技術(shù)成為 NAT(Network Address Translation,網(wǎng)絡(luò)地址轉(zhuǎn)換)。
為什么私網(wǎng) IP 不能出現(xiàn)在公網(wǎng)當(dāng)中?
不同的局域網(wǎng)中主機(jī)的 IP 地址可能是相同的,所以私網(wǎng) IP 無(wú)法唯一標(biāo)識(shí)一臺(tái)主機(jī),因此不能讓私網(wǎng) IP 出現(xiàn)在公網(wǎng)上,因?yàn)?IP 地址要能唯一標(biāo)識(shí)公網(wǎng)上的一臺(tái)主機(jī)。
但由于 IP 地址不足的原因,我們不能讓主機(jī)直接使用公網(wǎng) IP 而讓主機(jī)使用私網(wǎng) IP,因?yàn)樗骄W(wǎng) IP 可以重復(fù)也就意味著我們可以在不同的局域網(wǎng)使用相同的 IP 地址,緩解了 IP 的不足。
此外,我們不能直接使用公網(wǎng) IP 還有一個(gè)原因就是,因?yàn)槲覀兊臄?shù)據(jù)包必須要經(jīng)過(guò)運(yùn)營(yíng)商的路由器,如果我們發(fā)送的數(shù)據(jù)直接到了公網(wǎng),那也就意味著我們?cè)僖膊挥媒痪W(wǎng)費(fèi)了,這是不現(xiàn)實(shí)的。
兩個(gè)局域網(wǎng)當(dāng)中的主機(jī)不能不跨公網(wǎng)進(jìn)行通信
兩個(gè)局域網(wǎng)當(dāng)中的主機(jī)理論上是不能不跨公網(wǎng)進(jìn)行通信的,因?yàn)橐粋€(gè)主機(jī)要將數(shù)據(jù)發(fā)送給另一臺(tái)主機(jī)的前提是得先知道另一臺(tái)主機(jī)的 IP 地址。
即便現(xiàn)在這個(gè)主機(jī)知道了另一臺(tái)主機(jī)的 IP 地址,但有可能這兩臺(tái)主機(jī)的 IP 地址是一樣的,因?yàn)樗鼈兊?IP 地址都是私網(wǎng) IP 地址。
當(dāng)這一臺(tái)主機(jī)發(fā)送數(shù)據(jù)時(shí)將目的 IP 地址填成和自己相同的 IP 地址,操作系統(tǒng)就會(huì)認(rèn)為這個(gè)數(shù)據(jù)就是要發(fā)給自己的,而不會(huì)向外進(jìn)行發(fā)送了。
所以數(shù)據(jù)要從一個(gè)局域網(wǎng)發(fā)送到另一個(gè)局域網(wǎng),如果不經(jīng)過(guò)公網(wǎng)是基本上不可能的。我們?cè)诤蛣e人聊天的時(shí)候,也不是直接將數(shù)據(jù)從一個(gè)局域網(wǎng)直接發(fā)送到了另一個(gè)局域網(wǎng),而是先將數(shù)據(jù)經(jīng)過(guò)公網(wǎng)發(fā)送到了服務(wù)器,然后再由服務(wù)器將數(shù)據(jù)經(jīng)過(guò)公網(wǎng)轉(zhuǎn)發(fā)到了另一個(gè)局域網(wǎng)。
但實(shí)際確實(shí)存在一些技術(shù)能夠使數(shù)據(jù)包在發(fā)送過(guò)程中不進(jìn)行公網(wǎng) IP 的替換,而將數(shù)據(jù)正確送到目標(biāo)主機(jī),這種技術(shù)叫做內(nèi)網(wǎng)穿透,也叫做 NAT 穿透。
路由
數(shù)據(jù) “問(wèn)路” 的過(guò)程
數(shù)據(jù)在路由的過(guò)程中,實(shí)際就是一跳一跳(Hop by Hop)“問(wèn)路”的過(guò)程。所謂 “一跳” 就是數(shù)據(jù)鏈路層中的一個(gè)區(qū)間,具體在以太網(wǎng)中指從源 MAC 地址到目的 MAC 地址之間的幀傳輸區(qū)間。
IP 數(shù)據(jù)包的傳輸過(guò)程中會(huì)遇到很多路由器,這些路由器會(huì)幫助數(shù)據(jù)包進(jìn)行路由轉(zhuǎn)發(fā),每當(dāng)數(shù)據(jù)包遇到一個(gè)路由器后,對(duì)應(yīng)路由器都會(huì)查看該數(shù)據(jù)的目的 IP 地址,并告知該數(shù)據(jù)下一跳應(yīng)該往哪跳。
路由器的查找結(jié)果可能有以下三種:
路由器經(jīng)過(guò)路由表查詢(xún)后,得知該數(shù)據(jù)下一跳應(yīng)該跳到哪一個(gè)子網(wǎng)。
路由器經(jīng)過(guò)路由表查詢(xún)后,沒(méi)有發(fā)現(xiàn)匹配的子網(wǎng),此時(shí)路由器會(huì)將該數(shù)據(jù)轉(zhuǎn)發(fā)給默認(rèn)路由。
路由器經(jīng)過(guò)路由表查詢(xún)后,得知該數(shù)據(jù)的目標(biāo)網(wǎng)絡(luò)就是當(dāng)前所在的網(wǎng)絡(luò),此時(shí)路由器就會(huì)將該數(shù)據(jù)轉(zhuǎn)給當(dāng)前網(wǎng)絡(luò)中對(duì)應(yīng)的主機(jī)。
路由表查詢(xún)的具體過(guò)程
每個(gè)路由器內(nèi)部會(huì)維護(hù)一個(gè)路由表,我們可以通過(guò)route命令查看云服務(wù)器上對(duì)應(yīng)的路由表。
Destination代表的是目的網(wǎng)絡(luò)地址。
Gateway代表的是下一跳地址。
Genmask代表的是子網(wǎng)掩碼。
Flags中,U 標(biāo)志表示此條目有效(可以禁用某些條目)G 標(biāo)志表示此條目的下一跳地址是某個(gè)路由器的地址,沒(méi)有 G 標(biāo)志的條目表示目的網(wǎng)絡(luò)地址是與本機(jī)接口直接相連的網(wǎng)絡(luò),不必經(jīng)路由器轉(zhuǎn)發(fā)。
Iface代表的是發(fā)送接口。
當(dāng) IP 數(shù)據(jù)包到達(dá)路由器時(shí),路由器就會(huì)用該數(shù)據(jù)的目的 IP 地址,依次與路由表中的子網(wǎng)掩碼 Genmask進(jìn)行 “按位與” 操作,然后將結(jié)果與子網(wǎng)掩碼對(duì)應(yīng)的目的網(wǎng)絡(luò)地址Destination進(jìn)行比對(duì),如果匹配則說(shuō)明該數(shù)據(jù)包下一跳就應(yīng)該跳去這個(gè)子網(wǎng),此時(shí)就會(huì)將該數(shù)據(jù)包通過(guò)對(duì)應(yīng)的發(fā)送接口Iface發(fā)出。
如果將該數(shù)據(jù)包的目的 IP 地址與子網(wǎng)掩碼進(jìn)行 “按位與” 后,沒(méi)有找到匹配的目的網(wǎng)絡(luò)地址,此時(shí)路由器就會(huì)將這個(gè)數(shù)據(jù)包發(fā)送到默認(rèn)路由,也就是路由表中目標(biāo)網(wǎng)絡(luò)地址中的default??梢钥吹侥J(rèn)路由對(duì)應(yīng)的Flags是UG,實(shí)際就是將該數(shù)據(jù)轉(zhuǎn)給了另一臺(tái)路由器,讓該數(shù)據(jù)在另一臺(tái)路由器繼續(xù)進(jìn)行路由。
數(shù)據(jù)包不斷經(jīng)過(guò)路由器路由后,最終就能到達(dá)目標(biāo)主機(jī)所在的目標(biāo)網(wǎng)絡(luò),此時(shí)就不再根據(jù)該數(shù)據(jù)包目的 IP 地址當(dāng)中的網(wǎng)絡(luò)號(hào)進(jìn)行路由了,而是根據(jù)目的 IP 地址當(dāng)中的主機(jī)號(hào)進(jìn)行路由,最終根據(jù)該數(shù)據(jù)包對(duì)應(yīng)的主機(jī)號(hào)就能將數(shù)據(jù)發(fā)送給目標(biāo)主機(jī)了。
路由表生成算法
路由可分為靜態(tài)路由和動(dòng)態(tài)路由:
靜態(tài)路由:是指由網(wǎng)絡(luò)管理員手工配置路由信息。
動(dòng)態(tài)路由:是指路由器能夠通過(guò)算法自動(dòng)建立自己的路由表,并且能夠根據(jù)實(shí)際情況進(jìn)行調(diào)整。
路由表相關(guān)生成算法:距離向量算法、LS 算法、Dijkstra 算法等。