---
# System prepended metadata

title: 網路是怎樣連接的(三)瀏覽器與HTTP
tags: [計算機網路, ' 應用層', ' HTTP']

---

---
creator: zach
tags: 計算機網路, 應用層, HTTP
created: 2021-09-06 
---
# 網路是怎樣連接的(三)瀏覽器與HTTP
## 思考重點
- 網頁瀏覽器怎麼獲取網站消息
- 當我們輸入網時會發生什麼事
- 常見的404 not found意思
## 核心知識
![](https://i.imgur.com/dDHwFHL.png)

<center> 瀏覽器生成消息知識點 </center>

## 主要流程
網頁瀏覽器為了獲取服務器上關於該網站的HTML文件，透過HTTP協議向服務器發起請求，不過我們在網頁中是使用可以讓人看得懂的域名地址，因此網頁瀏覽器會調用socket庫中關於獲取DNS的函數，並把返回的IP地址與HTTP請求一併交給傳輸層，接下來作業系統會使用socket函數創建socket[^1]、利用IP地址與*Port*(端口號)與服務器建立連線、收發封包、最後斷開連結

[^1]:其實我們可以先把socket想像成兩個應用程式之間的連線狀態，相當於通信的"通行證"，卻好雙方狀態後就可以開始傳輸了
## HTTP
HTTP是甚麼?其實HTTP是超文本傳輸協定的縮寫，那麼大家一定好奇它究竟是什麼意思，其實可以這樣理解:

1. 超文本
	- 在早期文本指的是文字類型的內容，不過壓縮資料、文字、圖片這類內容在現在也可被HTTP視為是一種文本形式
	- 超文本，例如常見的*HTML*是將圖片、影片等內容的連結鑲嵌在一份文件上，我們只需要向代表連結的服務器發出請求即可獲取資料
	- HTML的內容是多個文本的連結與文字內容，不過透過瀏覽器的解釋，呈現給使用者的就是網頁內容
	- HTML文件中的連結不一定都指向不同的服務器端，有可能都存在於同一台服務器


![](https://i.imgur.com/OIYijr4.png)

<center> 解析HTML文件 </center>
</br>

2. 傳輸
	- 傳輸的定義是兩個實體可以透過發送資料來達成溝通的目的

3. 協定
	- 一種約定俗成的溝通方式，詳細請見[[計算機網路概述(一) 網路是甚麼#4 通訊協定]]

其實HTTP協議的核心概念就是，瀏覽器向指定服務器發出特定類型的需求，服務器再按照需求回傳資料給瀏覽器。其實說到底就是**針對誰**做**甚麼操作**，誰指的是URI，而操作指的就是方法
### 當我們輸入網址會發生甚麼事
![](https://i.imgur.com/tYYXPQ9.png)

<center>常見URL格式</center>
</br>

上圖示常見的URL格式，當我們在搜尋欄輸入一連串http://開頭字串時，這些網址準確的說就是*URL*(統一資源定位符)，他不一定是要用http://作為開頭，也可以是ftp://，這些都依照使用的應用程式而定

不過有人可能會好奇www.開頭的是否是另一種網路協定呢?其實不是，www就是*World Wide Web*的縮寫，是一種網頁命名方式，他是早期用來開發網頁以及HTML的編輯器名，算是一種歷史傳承吧

透過上圖可以發現URL其實就是網頁服務器中關於特定資料的文件路徑，透過取得該文件，我們就可以再瀏覽器上顯示出該網站的資訊了，不過網路的傳輸是使用所謂的IP地址，而非域名地址[^2]，這部份我們會在DNS部分介紹
#### URL解析
我們緊接著把上圖拆成5個部份來介紹，分別是:
1. 協定名
	- 應用層使用的通訊協定名稱
2. 身分認證訊息
	- 使用者名稱
	- 密碼
	- 有些服務器會需要使用者的身分認證才允許訪問
	- *此項可省略*
3. 網路器域名
	- 人們可以輕鬆看懂的網址格式，例如 www.yahoo.com.tw
4. 端口號
	- 指定服務器的端口號，若用戶省略則使用預設端口號
	- 網頁預設端口號為80
	- *此項可省略*
5. 文件路徑名
	- 類UNIX的文件系統表示法
	- 指向請求資源在服務器端的位置
##### 特殊表示法
但是可能有人會問，我在網址欄輸入URL時只有打上 www.xxx.com 阿，並沒有在字串尾部詳細加上資源路徑地址，這個URL是很精簡沒錯，那麼到底服務器能不能找到確切資料?
</BR>
![](https://i.imgur.com/IflBLSj.png)

<center>特殊的URL格式</center>
</BR>
一般來說URL會完整表示出檔案路徑，但是我們在瀏覽網頁時常常會看到以/為結尾的路徑名，其實URL的表達式可以允許文件名被省略，而且服務器會預先配置預設文件，假如文件名被省略的情況發生就去訪問它，一般來說預設文件會是index.html或default.htm

- 例如選手A就會訪問/dir/index.html文件
- 選手B直接連資料夾路徑都省略了，只訪問/[^3]根目錄，這種狀況服務器會訪問/index.html文件
- 選手C更過分，他連跟目錄都沒有告訴服務器，這種狀況只要服務器有事先配置好預設文件，那結果也跟選手B一樣會造訪跟目錄下的/index.html文件
- 選手D這個表達式更令人匪夷所思，它既不是/結尾的資料夾格式，也不是文件格式，那麼服務器該怎麼看待它呢?在這種情況下假如跟目錄下有名為newitem的資料夾就以該資料夾下的預設文件來處理，若是跟目錄下有名為newitem的文件名，則訪問該文件


>從這一部份可以帶出網頁瀏覽器的第一份任務&rarr;對URL進行解析，判斷**對誰**進行操作





#### URL與URI的差別
我們先說說URI的定義，**URI就是在某一規則下能把一個資源獨一無二的表示出來**，我們順著這個思路來舉個例子

![](https://i.imgur.com/Fp5sM93.png)

<center> 用URI的思路找尋學生 </center>
</BR>

假如我們透過學生證號來查詢該名學生，這個學號是**獨一無二的**，意思是在這個校園內不可能會有第二個擁有相同學號的學生，因此假若我們確切得知該生的學號那就一定可以確定是他
我們把焦點回到服務器上，例如文件名都有特定名稱: xxx.html或是給該文件設定特定編號html: xxx
- 這種使用專屬名稱或編號來表示檔案的方式就是URI的一種表達方式

同理我們使用絕對位置來尋找這名學生，透過電腦中遺留的線索發現他是哈哈大學電機系的學生，目前住在第二宿舍的301房2床，用這種絕對路徑的方式也可以將該生找出來，且是**獨一無二的**
這種表達方式我們並不陌生，例如 www.xxx.com.tw/dir/file/index.html ，就是列出該文件的絕對路徑
- 這種使用絕對路徑來表達檔案的方式是URL的達方式，但也符合獨一無二的特性，所以也是URI的表達方式

相反的，我們若是用鬆散的資料來查找，例如王曉明同學，誰知道這個學校有幾個王曉明?，電機系王同學會打排球?假如整個排球隊都姓王勒?~~(別說不可能)~~，這種沒辦法信誓旦旦地指出對方的方法就不屬於URI
</BR>
![](https://i.imgur.com/hHqXDZ5.png)

<center>URL是URI的一個子集合</center>
</BR>

說到底URL其實也是URI的其中一種，它只是用路徑定位的方式來表達唯一的文件，因此我們可以下一個結論: **URL是URI的一個子集合**

而在HTTP的發送請求中我們一般是將URL稱作URI，不過我個人更偏好URL，因為這樣從輸入網址到解析URL，再到HTTP消息封裝會更加直觀好懂，除非真的訪問一個有唯一編號名稱的/dir/123456789.html文件

#### 選擇方法
所謂的*method*(方法)就是對服務器下達特殊的指令，決定**對服務器進行什麼樣的操作**，我們稱之為方法，服務器接收客戶端請求後會按照方法來完成工作，以下介紹常見的幾種方法
</BR>

常見方法|含意|例子
:--:|:--:|:--:
GET|向服務器請求某個已經被URI定位的文件，目的是得到服務器返回響應|GET /dir/index.html </br>HOST: www.xxx.com.tw
POST|客戶端向服務器發送數據消息，一般來說在填表格或留言會用得上|POST /submit.cgi </br>HOST: www.xxx.com.tw</br>Content-Length: 1600[^4]
PUT|更新服務器上被URI指定的文件，若是沒有該文件則新創建一個|PUT /file.html </br>HOST: www.xxx.com.tw</br>Content-Type: text/html</br>Content-Length: 1600
HEAD|與GET方法類似，但只要求返回頭部消息，多用在檢查文件狀態|HEAD /dir/index.html </br>HOST: www.xxx.com.tw
DELETE|刪除服務器上被URI指定的文件|DELETE /dir/index.html </br>HOST: www.xxx.com.tw
OPTIONS|詢問URI指定的資源支持那些方法|OPTIONS* </br>HOST: www.xxx.com.tw
TRACE|服務器會返回它收到的請求。其目的是為了比對請求數據再傳輸過程中是否被竄改，Max-Foward字段在經過服務器時會減去1，直到變成0時則不再轉發消息|TRACE /</br>HOST: www.xxx.com.tw</br>Max-Fowards: 7
CONNECT|向代理服務器發起請求，要求建立TCP的Socket通道|CONNECT proxy.xxx.com:8080 </br>HOST: proxy.xxx.com
<center>常見HTTP方法</center>

### 瀏覽器發出請求
![](https://i.imgur.com/YyVxXEH.png)

<center>HTTP請求封包格式</center>
</BR>

其實在瀏覽器上的不同操作會觸發不同的方法，例如輸入網址與發送表單使用的方法是不一樣的。以下我們就大致介紹請求中各個區段的涵義
#### 方法
如上一小節所描述，就是對服務器請求的種類，比較要注意的是該方法是否需要使用到消息主體
#### 版本
瀏覽器使用的HTTP當前版本，常見如HTTP/1.1
#### 首部字段
儘管方法已經告知服務器請求內容，但有些狀況往往需要更具體的請求，例如日期、檔案要多新、檔案的長度、檔案的壓縮類型等等，這些就是首部字段的功用，**作為方法的補充**，再請求中常會見到3種首部字段，分別是請求首部字段、通用首部字段、實體首部字段[^5]

>為請求方法附加更多詳細內容的字段就是請求首部字，例如接受的文件類型、語言、長度等等

請求首部字段|含意
:--:|:--:|
Accept|可接受的文件類型
Accept-Encoding|可接受的編碼
Accept-Language|可接受的語言
If-Modified-Since|獲取資源的更新狀態
If-Range|若資源未更新時發送具有範圍的請求
Range|若資源未更新則依照這個範圍的byte作為請求

>通用首部字段就是請求與響應都會用到的首部字段，例如日期、選用連線狀態等等

通用首部字段|含意
:--:|:--:|
Cache-Control|控制服務器緩存
Connection|使代理刪除首部字段與持久連接控制
Date|創建封包的時間消息
Pragma|通常用在不接受緩存消息上
Transfer-Encoding|指定封包編碼方式
Upgrade|檢查是否要更高版本的協定可用

>補充請求與響應的消息主體附加訊息

實體首部字段|含意
:--:|:--:|
Content-Encoding|消息主體的編碼方式
Content-Language|消息主體使用的語言
Content-Length|消息主體的大小
Content-Range|消息主體的資料範圍
Last-Modified|資源的最後修改時間


#### 消息主體
**所有使用者需要的消息以及欲收發的文件都包含在這裡**

消息主體部分就會依照方法來決定是否要啟用，例如PUT與POST方法就需要加入一個文件到消息主體中，而GET僅需要方法、版本、首部字段就可以進行傳輸了
### 響應格式
![](https://i.imgur.com/n8YxbIi.png)

<center>HTTP響應封包格式</center>
</BR>

服務器完整收到客戶端發送來的請求後會依照請求方法來處理資料，並將文件處理的結果以及客戶端所需要的資料連同首部字段返回給客戶端，該資料封包就稱為HTTP響應，**其實HTTP響應與HTTP請求只差在狀態行與方法**，剩下的首部字段與消息主體邏輯是雷同的

#### 版本
同請求部分，只是響應的版本資訊放在第一個
#### 狀態行
![](https://i.imgur.com/pjNS2DJ.png)

<center>HTTP響應狀態碼</center>
</BR>

狀態碼就是服務器處理請求時的狀態描述，例如我們常見的*404 not found*就是服務器無法找到請求的資料位置的狀態回報，如上圖所示，我們會大概介紹一下常見的幾種狀態碼以及他們的含意
##### 1XX
1xx為一種過渡階段，表示請求正在處理中，不過這個狀態碼比較少見
##### 2XX
2xx表示客戶端請求已經被指定服務器接收，並且正確的處理，**這是我們最想看見的結果**，常見的狀態碼有:

狀態碼|含意|備註
:--:|:--:|:--:
200 OK|表示請求被正確處理，服務器依照需求返回客戶端需要的數據|--
204 No Content|請求被處理成功，但返回的響應不包含消息主體|一般運用在客戶端發送請求但不需要返回響應時
206 Partial Content|響應返回成功，但返回的消息主體只是整個消息主體的其中一部分|常見於HTTP的分批下載與斷點續傳


##### 3XX
目標資源位置發生變動，需要客戶端進行重定向處理

狀態碼|含意|備註
:--:|:--:|:--:
301 Moved Permanently|訪問的該資源已經永久移到別處，需要使用新的URI訪問|響應會附加Location首字段標示新的URI
302 Found|資源找到了，但暫時需要用另一個URI訪問|響應會附加Location首字段標示新的URI
304 Not Modified|服務器允許請求訪問資源，但資源並不符合請求的附加條件|其實該條狀態碼與重定向無關，另外響應不包含消息主體部分
##### 4XX
客戶端在訪問服務器時發生錯誤或缺乏權限

狀態碼|含意|備註
:--:|:--:|:--:
400 Bad Request|客戶端發送請求格式錯誤，服務器無法理解|--
403 Forbidden|客戶端沒有權限訪問該筆資源|--
404 Not Found|服務器不存在該資源|--
##### 5XX
服務器在處理請求的過程中發生錯誤，返回響應讓客戶端知道

狀態碼|含意|備註
:--:|:--:|:--:
500 Internal Server Error|服務器在處理請求時發生錯誤|也有可能是Web發生bug導致
501 Not Implemented|服務器尚不支援該請求的功能|--
503 Service Unavailable|服務器忙碌中，暫時無法處理客戶端請求|服務器會返回帶有Retry-After首部字段的響應，告訴客戶端等等再發送一次
#### 首字段
服務器響應中的首字段與請求大致相同，主要差別在**響應首部字段**。不過這並不並代表同一個請求與響應的通用首部字段與實體首部字段會完全相同，還是要依據消息狀態類型來判斷，只是說兩邊都有可能使用到相同的共用首字段，例如Date字段

>響應首部字段多用於補充資料消息以及告訴客戶端收到響應該做什麼

響應首部字段|含意
:--:|:--:|
Accept-Ranges|是否可以接受範圍請求
Age|告訴客戶端服務器在多久之前創立響應
Location|告知客戶端重定向URI位置
Retry-After|告知客戶端多久以後再發起請求

#### 消息主體
響應的消息主體就是服務器依照客戶端請求返回的文件或資料，消息主體的內容會以二進制方式表示

### 總結
最後我們可以利用這張簡單的示意圖來回想客戶端是如何利用HTTP協定與服務器溝通，從而獲得某個網站的頁面(該頁面有一個名為abc的圖檔)

![](https://i.imgur.com/XHk6maW.png)


[^2]:使用域名是方便使用者記住以及輸入網址，畢竟 www.google.com 比一連串數字好記多了吧
[^3]:/代表資料夾的跟目錄，它是目錄層級的最頂層，一般沒有名字。你可以在終端機中cd /看看會發生什麼事
[^4]:關於資料長度的首部字段，常見的首部字段可以查閱HTTP介紹文件
[^5]:其實我們不需要背這些字段的意思是甚麼，只要知道常用的幾個就可以了，其他不懂的字段名用到時再去查閱就可以了，要注意學習網路重要的是這些機制的交互行為、為什麼這麼做、為了解決什麼問題