---
# System prepended metadata

title: 網路是怎樣連接的(十一) 初探IP協議
tags: [' IP', 計算機網路]

---

---
creator: Zach
tags: 計算機網路, IP
created: 2021-10-26 
---
# 網路是怎樣連接的(十一) 初探IP協議
## 思考重點
- 封包是如何找到下一個端節點的
- IP地址在封包轉發中扮演的角色
- MAC地址在封包轉發中扮演的角色
- IP協議會為封包加上那些頭部
## 核心知識
![](https://i.imgur.com/n5eLN9D.png)
<center>核心知識點</center>

## 網路層實現的目的
網路層，主要負責**跨區段主機之間的通信**，所謂跨區段就是指電腦之間不是直接的連接，而是透過多個路由器、交換機或中繼器等端節點相連。該章我們主要探討IP封包如何進行轉發，以及它與MAC之間的關係

> **網路層與傳輸層對比**
> - 傳輸層提供進程與進程之間的相互連線服務
> - 網路層提供不同主機之間端到端的通訊服務

網路層目的在於解決兩個重要問題，分別是**如何依據IP地址進行互相通訊**，以及**如何透過路由控制決定下一步該往哪裡走**

IP地址提供一個類似於門牌號碼的功能，使得通訊有確切的目標。試想某天我們想從H市到Z市旅遊，雖然路途遙遠，但還好H市到Z市之間存在許多休息站。首先我們需要確認Z市的地址，並規劃每經過一個休息站後要選擇哪條路到達下一個休息站。這就好比查閱路由表然後將封包*轉發*出去，並將封包送達目標端節點

![](https://i.imgur.com/DO6yeNt.png)
<center>IP的包轉發</center>
</br>

在數據鏈路層的乙太網路協定中，處於同一個網域的主機可以透過查找對方MAC地址進行**直接**的通訊，但是傳輸層與網路層只關注目標主機的IP地址，中間的封包路線實際上怎麼轉發，其實是由MAC地址決定

這就導致的一個問題，既然相鄰的路由器們可以透過MAC地址找到對方，那麼透過路由表得到的指定IP地址該如何判斷是屬於哪台路由器?因此IP協議還需要**ARP協議**(*Address Resolution Protocol*)將路由表查找結果轉換成MAC地址，然後在下交給數據鏈路層以及物理層進行傳輸

![](https://i.imgur.com/8Xj9AKq.png)
<center>數據鏈路層與網路層關係</center>
</br>

從上圖可以看到數據鏈路層的關注重點在於**封包下一步該發給哪台相鄰路由器**，也就是說從的MAC地址表中挑選出適當的輸出端口。例如途中的R5路由器跳轉到R7的這個過程。相反的，網路層只需要知道我的IP位置以及對方的IP位置這樣就可以了。其實從本質上來看，整個流程的起始點相當於發送方MAC地址，終點相當於接收方MAC地址

數據鏈路層與網路層之間存在者互補關係，就好比老闆與秘書之間的關係。老闆決定本月的公司營運方向，秘書掌握老闆行程後安排這個月必須要開的會。先抓住大方向，在決定要如何落地實踐

## IP協議的連接特性
網路或通訊可以依照資料傳送的方法來進行分類，就是常見的**面向連接**與**非面向連接**。通訊前發送方與接收方主機需要先建立連接操作的稱為面向連接，如TCP協議需要進行握手才能開始收發操作。相反的不需要雙方主機互相確認即可傳送資料的稱為非面向連接操作，例如UDP與IP協議

至於為甚麼IP協議是非面向連接的，我們試著從反向思考，如果IP協議是面向連接操作的會怎樣?我們指定傳輸層使用TCP協議，它是一個面向連接的協議，也就是說在建立連線與斷開連線都要進行[握手操作](https://hackmd.io/@Zacch/rJdtuhsEF)，同樣也假設IP協議會進行類似的握手操作

先說結論，這會導致三大問題
1. 效率不佳
2. 分工模糊
3. 複雜性

首先談談效率問題，假若TCP發起SYN連線請求還需要IP協議先確認對方主機是否有連線，那不是多浪費時間嗎?而且就算IP協議真的確認對方主機準備好進行連線了，那不是和TCP在三次握手要做的事重複了嗎

軟體層面，需要多在網路層編寫一套負責確認雙方通訊的API，什麼時候算是建立連線成功、雙方握手的機制、甚麼時候將數據上繳給傳輸層等等，喔對了，還要修改一下IP頭部，增加幾個flag等等。原本這些判斷機制都由TCP包辦了，這樣做不僅沒有得到實質的效率提升，還使得網路分層更加模糊，每一層應該要做他最擅長的事才對

所以最好的方法就是IP協議只負責發送，**盡可能的將封包傳送到目標主機，但不保證封包會到達**，TCP借助IP協議實現的功能，在傳送封包的服務上又對封包的丟失、順序錯誤、逾時等問題提供**可靠的的解決方法**，確保接收方能正確地收到封包消息
## 封包的跳轉

![](https://i.imgur.com/nSozaTK.png)
<center>IP封包傳輸方式</center>
</br>

IP協議的實現目的就是要將封包發送給特定IP的端節點。途中封包會經過交換機、路由器最後到達目的地端節點。其中路由器與交換機不會實現所有的TCP/IP協議，交換機是根據乙太網工作的設備，而路由器因為需要執行路由控制所以包含了數據鏈路層與網路層

從上圖中可以看出當發送端的封包到達交換機時，交換機會透過內建的一組MAC地址表查找封包頭部對應的輸出端口，然後把封包發送給路由器，整個過程**不會修改**原封包的MAC頭部

緊接著封包到達路由器，首先路由器會捨去掉MAC頭部，然後依據封包IP頭部透過路由表決定下一次跳轉的IP地址，但由於相鄰路由器之間是靠MAC地址識別對方，所以網路層會使用ARP協議將查表得到的IP地址轉換為MAC地址，再由路由器的MAC地址表決定輸出端口，如此一來經過無數次跳轉便可以到達目標端節點

整個封包收發流程是由TCP委託IP協議進行發送開始的，IP協議會分別為封包添加**IP頭部**與**MAC頭部**，然後再委託數據鏈路層的網卡將封包轉換成電信號，最後透過實體的網路線路發送出去

> **容易搞混的IP頭部**
> 在整個封包轉發的過程，封包中的IP頭部是不會改變的，只有MAC頭部會不斷因為跳轉而改變，另外透過路由表查找到的IP地址**是為了轉換成MAC地址**，來進行相鄰節點之間的跳轉，並不會將該IP地址填入IP頭部

## IP頭部

![](https://i.imgur.com/gMhMa71.png)
<center>IPv4頭部</center>
</br>

**版本**

IP頭部版本資訊，占用4個bits。若是使用IPv4則填入4，IPv6則填入6

**頭部長度**

IP頭部長度，占用4個bits的長度，計算單位為4個bytes(上圖中的一列長度)。例如一個完整且包含選項的IP封包長度為4 \* 6 = 24bytes

**差異式服務編碼點與明示壅塞通知**

DSCP欄位用來進行品質控制，長度為6個bits。ECN欄位是用來通知網路壅塞的欄位，長度為2個bits。早期IP協議將將這兩個欄位，總計共8個bits定義成TOS(*Type of Service*)，代表IP的服務的品質，通常包含封包的優先級、最低延遲、最大吞吐量等參數

**封包長度**

表示連同IP頭部與資料的總長，通常代表的就是**整個IP封包的長度**，單位為byte，占用16個bits，所以可傳輸的最大封包長度為65535bytes

**識別碼**

用於識別封包的序號，若是IP進行封包分割時，同一個資料擁有相同的ID編號，長度為16個bits

**標誌位**

長度為三個bits，但只使用其中兩個bits，分別代表**是否允許封包分割**以及**判斷當前封包是否為分割包**

**分段偏移**

表示當前被分割的封包資料內容是從完整的IP封包的第幾個位元組開始的，占13個bytes

**存活時間**

表示封包可以經過路由器數量，每經過一台路由器TTL就會減1，若變成0封包就會被丟棄。由8bits組成，所以可以允許2的8次方也就是256次封包跳轉

**協議**

表示封包到達目的地後要將封包中的數據交給上層應用的哪個協議，常見的像TCP: 17, UDP: 06, ICMP: 01等，長度為8個bits

**頭部檢查碼**

用來檢查IP封包頭部在傳輸過程中是否發生改變，占用長度為16個bits

**發送方IP**

發送方的IP地址，占用長度為32個bits

**接收方IP**

接收方的IP地址，占用長度為32個bits

**選項**

通常在進行測試以及debug時才會使用，占用長度可自行調整

**填充**

用來將IP頭部長度調整成32bits的倍數，會在比特位填入0，占用長度不一

> IP封包中最重要的是接收方IP地址，它是由應用程式調用DNS解析器後，將返回值傳入給IP協議的
## 使用ARP協定
當路由器接收到封包後，會將IP頭部中的接收方IP地址與自己的路由表進行比對，決定下一次跳轉的裝置IP地址，不過我們都知道相鄰裝置之間必須透過MAC地址才能進行溝通，ARP協議實現的目的就是查詢代表該IP地址裝置的MAC地址

![](https://i.imgur.com/NDktZXu.png)
<center>ARP協議</center>
</br>

一般來說IP地址與MAC的對應關係會儲存在一個內存空間中，我們稱之為**ARP表**，裡面儲存位於同一個區域網路中IP地址與MAC地址的對應關係，經過查表後IP協議將該地址當成新的MAC頭部，然後透過MAC表決定該發給哪台相鄰路由器

但假如ARP表中無法找到指定IP地址時，我們就需要使用ARP查詢功能。ARP會使用ARP請求與回應來取得MAC地址，它會對位於同一個區域網路中的所有設備進行廣播，當設備IP地址與請求封包的IP地址相同時，該設備就會以MAC地址作為響應回傳 

不過若是連ARP查找功能都無法取得指定MAC地址的話，代表有可能這個區域網路內不存在該設備，亦者是從路由表有誤，這將導致這個封包被遺棄

由此我們得知IP協議會為封包加上兩種頭部消息，分別是IP頭部與MAC頭部，IP頭部只有發送方才會設置，之後的路由跳轉僅需要為封包更改MAC頭部即可

> 只有IPv4可以使用ARP協議，IPv6則是使用ICMPv6來取代ARP

## ARP表
每一次的ARP查詢都會更新一次ARP表，其實我們使用ARP查詢的目的是**盡可能減少使用ARP查詢**，畢竟向周遭設備進行廣播會一定程度上對網路造成負擔。另外ARP查詢不僅可以為發送請求主機更新ARP表，回應方也會依據ARP請求中的發送方MAC地址更新自己的ARP表

![](https://i.imgur.com/ocDufZv.png)
<center>ARP表</center>
</br>

在cmd中執行arp -a指定可以查看本機端的ARP表，經過ARP查詢新增的映射關係稱為動類型，透過手動配置的映射關係稱為靜態類型，不過若是一直使用ARP表也會出現問題，若IP地址發生變動就會發生錯誤，因此每隔一段時間ARP表中的動態類型表項就會被刪除，待重新發起ARP查詢時補全

> 其實只要安裝相應的作業系統，電腦也可以當成路由器使用

## MAC頭部
MAC地址長度為48bits也就是6個bytes，通常用6個兩兩一組的hex數字表示，使用'-'或':'進行分割都可以
```text
E0-D5-5E-20-D9-30
或是
E0:D5:5E:20:D9:30
```
最後我們來看看MAC頭部包含的內容，你可以把它想像成乙太網的通行證

![](https://i.imgur.com/yA43IyZ.png)
<center>MAC頭部</center>
</br>

**接收方MAC地址**
相鄰目標端節點的MAC地址，占用長度為48個bits

**發送方MAC地址**
發送源端節點的MAC地址，占用長度為48個bits

**乙太類型**
使用的協議類型，一般TCP/IP常用0800以及0806
- 000-05DC: IEEE 802.3
- 0800: IP協議
- 0806: ARP協議
- 86DD: IPv6協議






