🐱作者:一只大喵咪1201
🐱專欄:《網絡》
🔥格言:你只管努力,剩下的交給時間!
網絡層中,IP協議首部和有效載荷組成的完整數據稱為數據報。
IP協議
- 🍉TCP和IP的作用
- 🍉IP協議
- 🍉網段劃分
- 🍊IP地址分類
- 🍊內外IP和公網IP地址
- 🍉路由
- 🍉分片與組裝
- 🍉總結
🍉TCP和IP的作用
前面本喵講解了傳輸層的TCP和UDP協議,它們主要是用來控制數據在網絡中的傳輸的,像滑動窗口,超時重傳,確認應答,擁塞控制等等,都是在控制數據的傳輸。
在TCP/IP模型中,傳輸層的下一層是網絡層,傳輸層封裝好的數據段并不是直接交給了網絡,而是給到了網絡層,也就是我們今天要講解的IP協議。
- IP協議的作用:定位目標主機,具有將數據報從A主機跨網絡送到B主機的能力。
IP層是有這樣的能力,但是有能力就一定能辦到嗎?不一定,只能說有非常大的概率可以辦到。
既然是概率問題,就可以通過一些策略讓其成為百分之百的事情,比如沒有傳成功時就重傳,直到傳送成功,這樣一來就保證了IP協議傳送數據的可靠性。
- TCP協議就是給IP協議提供數據傳送策略的。
TCP協議又叫傳輸控制協議,它通過多種機制來保證數據能夠可靠的傳送到對端主機,但是它并不是執行者,真正的執行者是IP協議,TCP協議只是提供相關的策略讓IP協議執行,進而保證數據的可靠傳送。
🍉IP協議
和講解TCP協議的時候一樣,主要字段的作用穿插在后面具體內容中講解。
- 4位版本號(version):指定IP協議的版本,對于IPv4來說,就是4,這里本喵主要講解的就是IPv4。
- 4位頭部長度(header length):IP頭部的長度是多少個32bit, 也就是 length * 4 的字節數,和TCP的首部長度一樣,4個比特位表示最大的數字是15,因此IP頭部最大長度是60字節。
- 8位服務類型(Type Of Service):3位優先權字段(已經棄用),4位TOS字段,和1位保留字段(必須置為0)。
4位TOS分別表示:最小延時,最大吞吐量,最高可靠性,最小成本。這四者相互沖突,只能選擇一個。對于ssh/telnet這樣的應用程序,最小延時比較重要,對于ftp這樣的程序,最大吞吐量比較重要。
- 16位總長度(total length): IP數據報整體占多少個字節。
- 8位協議:表示上層協議的類型,UDP和TCP協議都有編號。
- 16位頭部校驗和:使用CRC進行校驗,來鑒別頭部是否損壞。
- 字段選項:略。
上面本喵提到的字段理解起來并沒有壓力,沒有提到的字段,在后面的具體內容中會詳細講解。
解包分用:
任何一個協議都必須考慮解包和分用,IP協議也不例外,要考慮對端的IP層是如果將報頭和有效載荷分離的,又是將數據交給傳輸層的哪個協議的?
在IP首部中,有4位首部長度,根據這個字段中的內容可以得到當前數據報報頭的長度,首部中還有16位總長度,可以得到整個數據報的長度,二者做差得到的就是有效載荷。
知道有效載荷后,只需要讀取固定字節數的有效載荷即可分離報頭。
在IP首部中,還有一個8位協議號,這里的編號就是要將數據交給的上層(傳輸層)協議的編號,如TCP或者UDP等,所以實現分用非常容易。
🍉網段劃分
如上圖所示便是IP層工作示意圖,這里有幾個基本概念:
- 主機:配有IP地址,可以進行網絡通信的設備,比如電腦,手機等等。
- 路由器:配有IP地址,又能進行路由控制,也就是將數據從一個節點傳送到另一個節點。
- 節點:主機和路由器的統稱。
上面說了,IP協議具有將數據從A主機跨網絡可靠的送到D主機的能力,那么IP協議是怎么從主機A找到主機D的呢?
- 路徑選擇中,目的IP地址非常重要,它決定了我們的路徑該如何走。
如上圖所示,IP協議報頭中有兩個IP地址字段,32位源IP地址標識的是主機A所在的位置,32位目的IP地址標識的是主機D所在的位置。IP地址就像生活中的家庭住址等地址一樣,都具有唯一性。
- IP地址 = 網絡號 + 主機號
IP地址采用的是點分十進制,IPv4的格式形如192.168.1.1
這樣的形式,共有四個字節,字節和字節之間用點隔開,每個字節的數字范圍是0~2555
,所以IP地址理論上的范圍是0.0.0.0~255.255.255.255
,這個范圍中有232個IP地址,也就是42億多,是不夠全球網民使用的。
網段劃分:
假設你現在從你的電腦上用微信發送了一條消息,這條消息第一步肯定是到騰訊的微信服務器上,服務器也是一個計算機,也是一個節點,它也有自己的IP地址。
此時你電腦上的數據也知道服務器的IP地址,但是怎么找到呢?你的電腦和服務器之間有無數個節點,難道要把42億多個IP地址遍歷一遍嗎?肯定不是的,這樣效率太低了。
所以要進行子網的劃分:
如上圖所示,本喵按照國家,省市區為單位來劃分子網,實際上的劃分并不是這樣的,而是按照人口區域來劃分的,本喵這樣劃分只是為了好理解。
世界上有眾多國家,每一個國家對應IP地址中4字節中第一個字節里的一個數字,如中國就是10.x.x.x
,日本是1.x.x.x
這樣。
每個國家里又劃分為多個行政區,拿中國來說,有34個省(自治區,直轄市,特別行政區),將IP地址中的第二個字節分配給這些省,第一個字節保持不變,如山東就是10.0.x.x
,上海就是10.2.x.x
這樣。
上海市又分為多個區,將IP地址中的第三個字節分配給這些區,第一個和第二個字節保持不變,如浦東就是10.2.0.x
,黃埔就是10.2.3.x
。
每個區中又有多臺主機,也就是有多個節點,包括服務器也是一個節點,將IP地址中的第四個字節分配給這些節點,如張三的電腦就是10.2.3.2
,騰訊的微信服務器就是10.2.3.4
。
- 上面劃分和實際情況沒有任何對應關系,只是為了方便理解。
假設你現在在日本,用微信發了一個消息,當數據到了IP層被封裝以后,報頭如上圖所示,源IP地址是1.1.1.1
,目的IP地址是10.2.3.4
。
數據被發送出去以后,首先到達的是你所在區子網的路由器,路由器發現目的IP中的前三個字節是10.2.3
,而整個日本子網的IP地址中第一個字節是1
,所以判斷這不是發給你所在國家的子網的,就將數據交給了上層路由器,最后到了日本的入口路由器。
- 每個子網都有一個入口路由器,該路由器是子網內部所有路由器的上層路由器,也叫做默認路由器。
日本的入口路由器和其他國家的入口路由器處于一個子網內,所以它肯定知道IP地址第一個字節是1
屬于哪個國家的,所以就將這個數據報直接發給了中國的入口路由器。
- 每一個入口路由器都橫跨兩個子網,一個是它所在的子網,還有一個是它下一層的子網。
中國的入口路由器橫跨所有國家入口路由器所在的子網,和中國內部所有省份所在的子網,所以它清楚的知道每個省份的IP地址中第二個字節的數字是多少。
中國的入口路由器拿到日本入口路由器發來的數據報以后,發現目的IP是10.2.3.4
,前兩個字節是10.2
,對應的是上海市,所以就將數據報直接發送到了上海市的入口路由器。
上海的入口路由器拿到這個數據報后,發現目的IP中的前3個字節是10.2.3
,對應的是黃埔區,所以就將數據報直接發送到了黃浦區的入口路由器。
黃埔區的入口路由器發現IP地址是10.2.3.4
,對應的是微信服務器,所以就將數據直接發送給了微信服務器的路由器。此時,數據報就被送到了目標地址。
上訴過程中,每一層子網只關注IP地址中的一個字節,越往下層,被確定的字節個數就越多,目標也就越明確,所查找的范圍也就越小。
通過子網劃分的方式,讓數據報每傳送一次就能排除大量的IP地址,比起遍歷的方式,效率提升的不是一星半點。
- 子網劃分的目的就是提高網絡通信數據傳輸的效率。
可以看到,在數據報傳送的過程中,根據IP地址中的前3個字節,可以將數據報通過多個路由器送到目標主機所在子網的入口路由器,此時也就確定了目標主機所在的子網絡,所以前三個字節被叫做網絡號。
目標主機所在子網的路由器再根據主機號,也就是IP地址中的最后一個字節來確定具體是哪個主機,然后將數據報發送到目標主機上。
- IP地址中的前3個字節被叫做網絡號,最后一個字節被叫做主機號。
如上圖所示,不同網段(子網)的網絡號必須不同,但是主機號可以相同,只要保證同一個網段內的所有主機號不同即可。
網絡號保證了兩個相連的子網具有不同的標識,主機號保證了同一子網內不同主機有不同的標識。
補充知識:
- IP地址中,主機號為0,如
192.168.128.0
就代表網絡號,等價于前三個字節192.168.128
,所以這個IP地址是不能綁定主機的。- IP地址中,主機號為1,如
192.168.128.1
代表當前子網的默認路由器(入口路由器),所以這個IP地址也不能綁定主機。
網段劃分是經過設計的,所以說互聯網是一個被設計過的世界,那么是誰設計的呢?答案是運營商,在我們國家就是移動,電信,聯通三大運行商,其他國家也有自己運營商。
運營商不僅設計了互聯網的網段劃分,而且搭建了物理層中的通信設備,使得網絡數據能夠在一根根網線中跑,進行網絡通信。
所以說,運營商是底層網絡的設計者,我們在使用網絡的時候,需要向運營商交錢,因為我們使用了人家的底層設計和設備。
不同的子網其實就是把網絡號相同的主機放到一起,如果在子網中新增一臺主機,則這臺主機的網絡號和這個子網的網絡號一致,但是主機號必須不能和子網中的其他主機重復。
通過合理設置主機號和網絡號,就可以保證在相互連接的網絡中,每臺主機的IP地址都不相同。
那么問題來了,手動管理子網內的IP,是一個相當麻煩的事情。
- 有一種技術叫做DHCP,能夠自動的給子網內新增主機節點分配IP地址,避免了手動管理IP的不便。
- 一般的路由器都帶有DHCP功能,因此路由器也可以看做一個DHCP服務器。
我們在日常生活中連接家里的wifi時,第一次連接需要輸入賬號和密碼,這其實就是在向路由器申請IP地址,在沒有聯網的時候,你的設備是沒有IP地址的。
🍊IP地址分類
過去曾經提出一種劃分網絡號和主機號的方案,把所有IP 地址分為五類, 如下圖所示:
- A類:0.0.0.0到127.255.255.255
- B類:128.0.0.0到191.255.255.255
- C類:192.0.0.0到223.255.255.255
- D類:224.0.0.0到239.255.255.255
- E類:240.0.0.0到247.255.255.255
其中網絡號和我們前面網段劃分中是一樣的,也是用來標識不同的子網的,只是不同類型IP地址網絡號的范圍不一樣,主機號的范圍也不一樣。
某一個子網會領取幾類IP地址去使用,其中用的最多的是B類IP地址,隨著網絡的飛速發展,這種劃分方案的局限性很快顯現出來,大多數組織都申請B類網絡地址,導致B類地址很快就分配完了,而A類卻浪費了大量地址。
- 例如,申請了一個B類地址,理論上一個子網內能允許6萬5千多個主機,A類地址的子網內能包含的主機數更多。
- 然而實際網絡架設中,不會存在一個子網內有這么多的情況,因此大量的IP地址都被浪費掉了。
因為有組織已經申請了一個A類IP地址,即使主機數沒有那么多,沒有用完,但是別的組織也不能申請這個A類的IP地址了,因為網絡號是唯一的。
此時就導致A類IP地址存在大量的浪費,而B類IP地址嚴重不足。
- 針對這種情況提出了新的劃分方案,稱為CIDR(Classless Interdomain Routing)。
- 也就是現在采用的子網劃分方式,不區分IP地址的類型,就像本喵前面劃分子網時那樣。
- 引入一個額外的子網掩碼(subnet mask)來區分網絡號和主機號。
- 子網掩碼也是一個32位的正整數,通常用一串 “0” 來結尾。
- 將IP地址和子網掩碼進行 “按位與” 操作,得到的結果就是網絡號。
- 網絡號和主機號的劃分與這個IP地址是A類、B類還是C類無關。
子網掩碼的存在就是為了區分網絡號和主機號的,可以通過IP地址和子網掩碼按位與高效的得到網絡號。
子網掩碼和IP地址做“與”運算,分離出IP地址中的網絡地址和主機地址,用于判斷該IP地址是在本地網絡上,還是在遠程網絡網上。
如上圖所示,一個路由器收到了一個IP數據報,其中目的IP地址是140.252.20.68
,該路由器所處網段的子網掩碼是255.255.255.0
,將IP地址和子網掩碼按位與后得到的網絡號是140.252.20.0
。
然后與自己所處網段的網絡號進行比較,如果相同,直接將數據給到本網段的子網中,如果不同,則需要跨網段,則將數據給到上一層路由器去處理。
- 得到的網絡號所標識的子網中,節點的地址范圍是
140.252.20.0~140.252.20.255
。- 也就是主機號從全0到全1。
再看一個例子,如上圖所示,此時的子網掩碼是255.255.255.240
,按位與以后得到的網絡號是140.252.20.64
,作用和上面一樣,也是用來判斷目的IP是否位于本網段。
P地址和子網掩碼還有一種更簡潔的表示方法,例如140.252.20.68/24
,表示IP地址為140.252.20.68
,子網掩碼的高24位是1,也就是255.255.255.0
。
- 兩個例子中,網絡號的位數是變化的。
第一個例子中,網絡號是前3個字節,第二個例子中網絡號是前3個字節加4個比特位,剩下的才是主機號。
- 數據在傳送的過程中,網絡號是變化的。
繼續拿前面的國家和省市之間網絡拓撲結構來說,從日本發送出來的微信消息現在已經交到了中國入口路由器,假設中國網段的子網掩碼是255.0.0.0
。
- 每個路由器中都維護著一張路由表,里面存放著下層所有子網的網絡號和子網掩碼。
中國網段入口路由器將IP地址與它所知道的子網掩碼遍歷,進行按位與,最后發現該IP地址和上海的子網掩碼255.255.0.0
按位與后得到的網絡號和上海的網絡號相同,然后將該數據交給上海子網的入口路由器。
上海入口路由器同樣進行上面的操作,最后發現該IP地址和黃浦區的子網掩碼255.255.255.0
按位雨后得到的網絡號和黃浦區的網絡號相同,然后將該數據交給黃埔區入口路由器。
黃浦區入口路由器根據IP地址中的主機號找到微信服務器,至此,數據完成傳送。
- 在上面數據從中國入口路由器傳送到黃浦區入口路由器的過程中,網絡號是不停變化的。
- 越上層的子網掩碼位數越少,也代表著網絡號所位數越少。
特殊的IP地址:
- 將IP地址中的主機號全部設為0,就成了網絡號,代表這個子網,如
140.252.20.0
。 - 將IP地址中的主機號全部設置為1,就成為了廣播地址,用于給同一個子網中的所有主機發送數據,如
140.252.20.255
。 - IP地址
127.*
用于本機環回測試,通常是127.0.0.1
,只能在本主機上進行網絡通信。
IP地址的數量限制:
我們知道,IP地址(IPv4)是一個4字節32位的正整數,一共只有 232個IP地址,大概是43億左右。而TCP/IP協議規定, 每個主機都需要有一個IP地址,難道這意味著,一共只有43億臺主機能接入網絡么?
實際上,由于一些特殊的IP地址的存在,數量遠不足43億。另外IP地址并非是按照主機臺數來配置的,而是每一個網卡都需要配置一個或多個IP地址。
CIDR(Classless Interdomain Routing) 雖然在一定程度上緩解了IP地址不夠用的問題(提高了利用率, 減少了浪費, 但是IP地址的絕對上限并沒有增加),仍然不是很夠用,這時候有三種方式來解決:
- 動態分配IP地址:只給接入網絡的設備分配IP地址,因此同一個MAC地址的設備,每次接入互聯網中,得到的IP地址不一定是相同的。
- NAT技術(后面會重點介紹)。
- IPv6:IPv6并不是IPv4的簡單升級版,這是互不相干的兩個協議,彼此并不兼容。IPv6用16字節128位來表示一個IP地址,但是目前IPv6還沒有普及。
🍊內外IP和公網IP地址
如果一個組織內部組建局域網,IP地址只用于局域網內的通信,而不直接連到公網上,理論上使用任意的IP地址都可以,但是RFC1918規定了用于組建局域網的私有IP地址范圍:
10.*
,前8位是網絡號,后24位是主機號,所以共有16777216個地址。127.16
到127.31
,前12位是網絡號,后20位是主機號,所以共有1048576個地址。192.168.*
前16位是網絡號,后16位是主機號,所以共有36636個地址。
在這個范圍中的IP地址都稱為內網IP(私有IP),其余的都稱為公網IP(全局IP)。
如上圖所示,路由器橫跨兩個子網,那么它必然配有兩個IP地址,一個是WAN
口IP,位于上層子網,就像前面網絡拓撲結構中,上海市的入口路由器和其他省路由器組成的子網中,WAN
口IP就是該路由器在這個網段中的IP地址。
另一個IP地址是LAN
口IP,位于當前子網,上海的入口路由器和上海所有區組成的子網中,LAN
口IP就是該路由器在這個網段中的IP地址。
- 和路由器
LAN
口連接的主機,都屬于當前這個路由器的子網中。- 子網內的主機IP地址不能重復,但是子網之間的IP地址就可以重復了。
上圖中,所有家用路由器的子網IP(LAN
口IP)都是192.168.1.1/24
,這個IP地址是用來和家里與這個路由器相連的所有設備進來通信的,每一個家用路由器和與它相連的設備組成了一個局域網。
- 在這個局域網中,路由器的子網IP
192.168.1.1
就是唯一的。
但是左邊的兩個家用路由器的WAN
口IP不同,因為它兩和運營商路由器的LAN
口IP組成一個子網(局域網),該子網中的IP地址都是唯一的。
上圖中,兩個運營商路由器的子網IP又是相同的,都是10.1.1.1/24
,因為這個LAN
口IP只用于該從屬該路由器的子網中通信,在這個子網中也是唯一的。
兩個運營商的WAN
口IP是不相同的,而且是122.*
,這個IP地址是公網IP,所以這兩個WAN
口IP地址是用來在公網之間通信的。
- 局域網中:一個子網中所有節點的IP地址都不能相同,要具有唯一性。不同子網中的IP地址可以相同。
- 公網中:IP地址必須具有唯一性,不論屬于哪個子網。
本喵前面畫的網絡拓撲結構中,是公網網段劃分理想示意圖,沒有加入任何內網,實際上在到達某個省或者某個市就開始采用內網(局域網)的方式了。
就像我們平時在微博,抖音等軟件里的評論歸屬地一樣,只能看到所在省,無法看到再具體的信息了,因為省使用的還是公網IP,非常好識別,再網下使用的就是內網IP,就比較復雜了,好識別。
既然不同的內網中可以有相同的IP地址,那么就出問題了:
假設我現在從我的電腦上發送了一份數據到服務器上,IP報頭如上圖所示,源IP地址是192.168.204/24
,這是一個內外IP地址,目的IP地址是122.77.241.3/24
,這是一個公網IP地址。
你將數據從你的電腦上發送出去后,首先交給了家用路由器,家用路由器用子網掩碼按位與后發現不是發送到本網段的,然后交給了運營商路由器。
運營商同樣判斷出不是發送給本網段的,而是要發送給公網中的服務器的,所以運營商路由器將數據發送給了服務器。
服務器收到數據以后通過特定進程處理,處理完進行響應,但是響應數據段到了IP層以后,發現目的IP是192.168.1.1
,這是一個內網IP,填入到IP報頭中的目標IP地址字段里,然后發到公網中。
但是由于這是一個內網IP,所有運營商路由器都不認識,并且它們的子網中都有這個IP地址,所以就會導致服務器的響應無法傳送到我的電腦上。
- 內網中的主機需要和公網網進行通信時,路由器將IP首部中的目的IP地址進行替換(替換成
WAN
口IP),這樣逐級替換,最終數據包中的目的IP地址成為一個公網IP。- 這種技術稱為NAT(Network Address Translation,網絡地址轉換),具體詳細內容本喵以后會講解。
如上圖所示,在從你的電腦將數據發送到家用路由器時,IP報頭中的目的IP是192.168.201/24
,是一個內網IP地址。
家用路由器將數據發送給運營商路由器的時候,將IP報頭中的目的IP地址替換成了自己的WAN
口IP10.1.1.2/24
,同樣是一個內網IP地址,但是屬于你電腦的上一層。
運營商路由器在將數據發送到公網中給服務的時候,將IP報頭中的目的IP地址替換成了自己的WAN
口IP122.77.241.4/24
,這是一個公網IP,在全網都具有唯一性。
此時服務器在處理完數據做出響應時,構建的IP數據報中目的IP就填運營商的WAN
口IP地址122.77.241.4/24
,將數據發到公網中后可以準確發回運營商路由器,然后再由運營商路由器發給它子網的路由器,最終到了你電腦上。
🍉路由
- 路由:就是在復雜的網絡拓撲結構中找出一條通往終點的路線。
- 一跳: 就是數據鏈路層中的一個區間,具體在以太網中指從源MAC地址到目的MAC地址之間的幀傳輸區間。
通俗來說,一跳就是兩個節點相連之間的路徑。路由的過程就如上圖那樣一跳一跳的問路的過程。
當IP數據報到達路由器以后,由路由器決定這個數據包是直接發送給目標主機還是需要發給上一層路由器。如果目標IP地址在本網段內就直接發送給目標,否則就發送給上一層路由器。
那么路由器是如何判斷當前這個IP數據報該發送到哪里呢?這就要靠每個路由器(節點)內部維護的路由表了。
如上圖所示,在Linux上,使用route
指令可以查看當前機器上的路由表,我們的計算機也有路由功能,也是可以看作一個路由器的。
使用上圖所示的路由表來講解,本喵刪除了Metric
和Ref
兩列,因為現在不用關心它是什么意義。
這臺主機有兩個網絡接口,一個網絡接口eth0
連到192.168.10.0/24
網絡,另一個網絡接口eth1
連到192.168.56.0/24
網絡。
路由表的Destination
是目的IP地址,Genmask
是子網掩碼,Gateway
是下一跳地址,也就是下一個路由器IP地址。Iface
是發送接口,是物理上存在的接口,該接口通過網線和對應網絡相連。
Flags
中的U
標志表示此條目有效(可以禁用某些條目),G
標志表示此條目的下一跳地址是某個路由器的地址,沒有G
標志的條目表示目的網絡地址是與本機接口直接相連的網絡,不必經路由器轉發。
- 轉發過程例1: 如果要發送的數據報的目的IP是
192.168.56.3
跟第一行的子網掩碼做與運算得到192.168.56.0
,與第一行的目的網絡地址不符,再跟第二行的子網掩碼做與運算得到192.168.56.0
,正是第二行的目的網絡地址,因此從eth1
接口將數據報發送出去。
由于192.168.56.0/24
正是與eth1
接口直接相連的網絡,因此可以直接發到目的主機,不需要經路由器轉發。
- 轉發過程例2: 如果要發送的數據包的目的地址是
202.10.1.2
依次和路由表前幾項進行對比,發現都不匹配,說明目的IP不在本網段,按缺省路由條目(最后一行),從eth0
接口發出去,發往IP地址為192.168.10.1
的路由器,由192.168.10.1
路由器根據它的路由表決定下一跳地址。
總的來說,當一個數據報文到來節點后,會經過四步來完成數據報文發送:
- 遍歷路由表
- 目的IP和路由表中的每一行的子網掩碼按位與,確定該數據報要去的目標網絡。
- 對比結果和目標網絡
- 最后通過
Iface
接口發出報文。
如上圖紅色框所示,IP協議報頭中有一個字段叫做8位生存時間(TTL),該字段的值表示跳數。
在整個網絡拓撲結構中,存在非常多的節點,數據報在發送的過程中會經過這些節點,如果某個或者某些路由器發生故障,則有可能導致數據報在網絡中的傳送路徑變成環狀,在固定路由器之間循環,始終到不了目標IP地址。
發送端遲遲得不到應答,就會觸發超時重傳機制,然后新發的數據報又會陷入到循環中,導致網絡中數據越來越多,最后就擁塞了。
此時8位的生存時間就派上用場了,假設生存時間字段的值是10,那么數據報在網絡中每進行一跳該值就會減一,如果減到0這個數據報就消亡了。
- 8位生存時間的最大值是255,也就是說一個數據報最多進行255跳。
- 255跳可以到達整個網絡中的任何一臺主機了,不會存在還沒有到達數據就消亡了,除非路由出現了問題。
- 在數據傳送的過程中,類似于多叉樹的模型,每一跳就在向下遍歷,能排除相當多的主機。
🍉分片與組裝
如上圖所示,IP協議報頭的第二行就是用來實現分片與組裝的。
為什么要分片?
我們知道,在TCP/IP模型中,網絡層的下一層是數據鏈路層,網絡層中的IP協議并不是把數據直接發送到了網絡中,而是交給了數據鏈路層,數據鏈路層才是真正將數據發送到網絡中。
數據鏈路層中使用的是MAC
幀協議,該協議規定自己的有效載荷不能超過1500個字節。雖然可以修改,但是這里我們不考慮,就按默認情況來說。
如上圖所示,IP層位于TCP層和數據鏈路層之間,IP層發送的數據是TCP層交付下來的,交付多少就向數據鏈路層發多少。
此時TCP層交付給IP層3000個字節的數據,IP層向下交付的時候,數據鏈路層說它最多只要1500個字節,否則就不要。
- 數據量的多少并不是IP層決定的,而是由TCP層決定的。
所以此時IP層就非常委屈,上面是領導要求發送3000個字節,下面員工只能處理1500個字節,面對這個矛盾,IP層只能自己想辦法,所以就將數據分片,分成多個數據包,每個數據包不超過1500個字節,然后分多次交付給數據鏈路層。
同樣的,當這些分開的數據報發送到對端后,對端的IP層需要進行組裝,將分片的數據拼裝成一個完整的數據。
- 分:自己的IP層完成。
- 組:對端的IP層完成。
- TCP層和數據鏈路層完全不關心IP層進行了分片,實現了高度解耦。
再來看,IP報頭第二行的32位字段:
- 16位標識(id):發送的每一個數據報該標識都是唯一的,如果IP報文在數據鏈路層被分片了,那么每一個片里面的這個id都是相同的。
- 3位標志字段: 第一位保留(保留的意思是現在不用, 但是還沒想好說不定以后要用到)。第二位置為1表示禁止分片,這時候如果報文長度超過
MTU
(1500個字節) IP數據報就會丟棄報文。
第三位表示更多分片,如果該數據報被分片了的話,這個第三位就是1,最后一個分片由于不會再分了,所以是0。
如上圖所示,將3000字節的數據報分片為兩個1500字節的數據報,每個數據再加一個IP報頭,其中第一個數據報是3000字節的前半部分,它被分片了,所以報頭中的第三個標志位是1。
第二個數據報是3000字節的后半部分,它沒有再分片,所以IP報頭中的第三個標志位是0。
- 13位分片偏移(framegament o?set):是分片相對于原始IP報文開始處的偏移,實際偏移的字節數是這個值 * 8 得到的。
繼續看前面分片的圖片,第一個數據報是從頭開始分片的,所以片偏移量就是0,第二個數據報是從1500字節處開始分的,所以片偏移量值*8就是1500。
除了最后一個報文之外, 其他報文的長度必須是8的整數倍(否則報文就不連續了),本喵按照1500字節拆分就不是8的整數倍。
- 對端IP層收到數據報后怎么知道這是一個被分片了的數據報?
數據鏈路層不關心IP層是否分片了,它只管發,所以對端的IP層收到數據報后需要知道這是一個被分片了的報文。
- 如果更多分片標志位(第三個標志位)是1,說明該數據報被分片了。
- 如果更多分片是0,并且片偏移值大于0,說明該數據報被分片了。
- 同一個報文的所有分片對端是如何識別出來的?
由于16位標識符的存在,對端收到的數據報中,標識符相同的數據報組合起來就是一個完整的數據報。
- 哪一個數據報是第一個分片,哪一個是最后一個分片?
更多分片標志位是1,片偏移量是0,說明這是第一個分片。更多分片標志位是0,片偏移量大于0,說明這是最后一個分片。
- 哪個分片在前,哪個分片在后?
將所有分片的片偏移量按照升序排序,就可以知道哪個分片在前,哪個分片在后。
- 有沒有收全或者丟失分片呢?
當前分片的起始位置+自身數據長度,如果等于下一個分片中的片偏移量,說明這兩個分片是挨著的,如次反復判斷,便能判斷出是否收全了,只要有一次判斷結果不相等,那么就說明有數據片丟了。
- 怎么保證對端組裝起來的報文是正確的?
- IP協議有16位首部校驗和,校驗通過會分發給上層TCP協議。
- TCP協議也有校驗和,可以判斷出數據是否是正確的。
假設傳送一個報文的成功率是99%,將一個長的數據報分片成兩個以后,兩個數據報的傳送的成功率就是99%2 = 98.01%,這個大數據報傳送的成功率就降低了。
一個數據報被分片成多個,任意一個丟失就會導致對端IP層組裝失敗,從而導致發送發TCP層超時重傳。
- 分片和組裝并不好,而且這種情況也并不是經常的,并不是主流方式。
🍉總結
IP協議中,最重要的字段就是IP地址,IP協議是專門負責路由的,所以要重點理解整個網絡的拓撲結構,包括子網劃分,公網和內網(局域網)的劃分和路由。