---
# System prepended metadata

title: '電腦網路 Chapter 2 : Application Layer'
tags: [電腦網路, ' 大二筆記']

---

---
tags: 電腦網路, 大二筆記
---

# 電腦網路 Chapter 2 : Application Layer
## Principles of Network Applications
### 網路應用程式架構 Network Application Architecture
#### 主從式架構 Clinent-server Architecture
* 主從式架構中，一定有個 **伺服器 (Server)** 來服務 **客戶端 (Client)** 所發送來的請求
* 伺服器 Server
    * 不會關機
    * 擁有固定的 IP 位址
    * 通常位於 **資料中心 (data center)**，以提供大量的流量服務
* 客戶端 Client
    * 向伺服器端發送請求
    * 浮動 IP 位址
    * 每個客戶端無法互相溝通
* 基於主從式架構的服務：HTTP, FTP, Email

#### 對等式架構 Peer-to-peer Architecture
* 不需要依賴資料中心的伺服器，而是對等的主機互相連接，因而稱為 **peer-to-peer (P2P)**
* 去中心化，在資源的使用上較有效率，但是缺乏安全性
* P2P 具備 **自我擴展性能 (Self Scalabiliity)**，可根據需求自動調整以實現更高的可擴展性和性能
* 主機間的 IP 會浮動，所以常常會使用混和式架構：伺服器用以追蹤各個客戶端的 IP，而通信則是使用 P2P 的方式在電腦間互傳

### 程序間溝通 Processes Communicating
* 兩個執行在不同終端裝置上的 **程序 (Process)** 需要透過網路來交換 **訊息 (Message)**
* 會有專門的程序將訊息發送到網路上，也有專門收訊息的程序

#### Client and Server Processes
* 我們將兩個進行通訊的程序分為 **客戶端 (Client)** 和 **伺服器端 (Server)**
    > 無論是在主從式架構或是 P2P 都是以這種方式，發起通訊的電腦會被定義為 **客戶端**

#### 插座 Socket
* 兩個網路應用程式透過網路傳遞訊息使用的介面
* 應用程式將訊息由 Socket 送出至傳輸層，而傳輸層會幫助將訊息送到目的地；收信方也需要透過自己的 Socket 去收取信息
![Socket](https://hackmd.io/_uploads/H1-iV4pJR.png)
* 可以看到 Socket 是位於應用層和傳輸層中間溝通的介面，因此又稱為應用程式與網路間的 **應用程式介面 (Application Programming Interface, API)**
* 開發者只對應用層有操控權，上到傳輸層就由系統控制

#### Addressing Processes
* 電腦傳輸信息時，除了需要知道收信端程序的位址，還要知道是哪個程序要收信。因此程序需要一個 **識別符 (Identifier)**：
* 識別符內容包含：
    * **IP 位址**：收信電腦的位址
    * **埠號 (Port)**：用以辨別收信的程序 (準確來說是 Socket)

#### 應用層協議 Application-layer Protocol
* 協定內容：
    * 交換訊息的形式
        * request, response...
    * 訊息的語法
        * 有哪些欄位，欄位怎麼分配
    * 訊息的語意
        * 欄位代表的意義
    * 規則
        * 送出或接收到訊息後要做的事情
* Open Protocol
    * 通用的協定，大家都可以通用
    * HTTP, SMTP
* Proprietary Protocol
    * 私人的協議
    * Skype

### Transport Services Available to Applications
傳輸層協定提供的程式服務大致分為四個面向：
#### 資料完整性 Data Integrity
* 有些應用程式不能遺失封包，例如網路銀行轉帳
* 有些協議能提供某種機制，保證封包能完整到達目的地，我們稱他提供 **可靠的資料傳輸 (Reliable Data Transfer)**
* 不是每個應用程式都需要，例如大部分的語音及視訊通話，掉包頂多延遲而已
#### 吞吐量 Throughput
* 一些應用程式需要一定的吞吐量來維持品質，如語音通話
* 這種對吞吐量有要求的應用程式我們稱為 **對頻寬敏感的應用 (Bandwidth-sensitive Application)**
* 而相對的 **有彈性的應用程式 (Elastic Application)** 對吞吐量的要求不大，有多少用多少。如：網頁服務、Email
#### 時間差 Timing
* 網路遊戲、網路電話這種需要低網路延遲的應用程式，就需要保證其封包傳輸的時間差
#### 安全性 Security
* 傳輸層協定可以提供跟安全性有關的服務
* 加密、資料完整性和終端身分驗證
    > 這裡的資料完整性比較像是：確保資訊不受未授權的竄改或在竄改後能及時被發現

|應用服務|是否能忍受掉包|對吞吐量的需求|對最大時差是否有要求|
|:-:|:-:|:-:|:-:|
|**檔案傳輸/下載服務**|不能掉包|沒有特殊需求|沒有要求|
|**Email**|不能掉包|沒有特殊需求|沒有要求|
|**網頁服務**|不能掉包|沒有特殊需求（只會用固定幾 kbps）|沒有要求|
|**網路電話/視訊會議**|可以掉包|音訊: few kbps - 1 Mbps<br>影片: 10 kbps - 5 Mbps|不得超過 100 msec|
|**影音串流**|可以掉包|同上|不能超過數秒|
|**互動式遊戲**|可以掉包|few kbps - 10 kbps|不得超過 100 msec|
|**文字訊息**|不能掉包|沒有特殊需求|有時有有時沒有|

### Transport Services Provided by the Internet
#### TCP Service
* 可靠的資料傳輸 Reliable Transport
    * TCP 可以確保傳送出去的資料都能完整的並按照順序送到收信端
* 流量控制 Flow Control
    * 保證收發兩端的傳輸速度保持一致
* 壅塞控制 Congestion Control
    * 將長度過長的訊息切小，壅塞時自動降速
* 連線導向的服務 Connection-oriented Service
    * TCP 規定兩台電腦傳遞訊息 **之前**，要先進行 **交握 (Handshaking)**
    * 當交握完成，我們會說一個 **TCP 連線** 存在於雙方的 **Socket** 之間
    * 為 **全雙工 (Full-duplex)** 的連線，雙方可以同時傳訊息給對方
    * 傳輸完成後，連線就必須關閉
* **並沒有** 提供
    * 時間差
    * 最低頻寬保證
    * 安全性
#### UDP Service
* 提供最輕量化的傳輸協定，講難聽點就是啥都沒有
* 資料傳輸前不需要交握，也沒有可靠的資料傳輸
* 代表把資料丟進 UDP 的 Socket，不保證資料一定能到對方手上，順序也無法保證
* **沒有** 提供
    * 可靠的資料傳輸
    * 流量控制
    * 壅塞控制
    * 連線的建立
    * TCP 沒有的服務

|應用服務|應用層協定|底下的傳輸層協定|
|-|-|-|
|**電子郵件**|SMTP [RFC 5321]|TCP|
|**遠端終端機存取**|Telnet [RFC 854]|TCP|
|**網頁服務**|HTTP [RFC 2616]|TCP|
|**檔案傳輸**|FTP [RFC 959]|TCP|
|**多媒體串流**|HTTP (e.g., Youtube)|TCP|
|**網路電話**|SIP [RFC 3261], RTP [RFC 3550]，或是專有軟體 (e.g., Skype)|UDP or TCP|

電子郵件、終端機存取、網頁服務及檔案傳輸都無法容忍掉包，需要可靠的資料傳輸，因此選用 TCP；而網路電話可以容忍掉包，但對於最小傳輸速率有要求，因而使用 UDP，可以規避一些 TCP 的流量控制及壅塞控制

#### Securing TCP
可以發現，原本的 TCP 是沒有加密服務的，那上傳密碼不就被看光光
* 傳輸層安全協定 Trnasport Layer Security, TLS
    * 提供加密的 TCP 連線
    * 資料完整性 (Data Integrity) 
        > 確保信息沒有遭竄改
    * 提供端點認證 (End-point Authentication)

## Web and HTTP
### HTTP Overview
超文本傳輸協定 (HyperText Transfer Protocol, HTTP)，為網頁所使用的應用層協定
* **網頁 (Web Page)**，由多個物件組成
* **物件 (Object)** 是一個簡單的檔案，例如：HTML頁面、圖片或影片。每個物件都能用一個 **URL** 來定址
* 大部分網頁都由一個 **Base HTML-file** 和多個被 **參照 (referenced)** 的物件組成
* **URL** 用以參照物件，每個 URL 都有兩個部分
    * 主機名稱 (下圖的 ```www.someSchool.edu```)
    * 檔案路徑 (下圖的 ```someDepartment/picture.gif```)
    ```
    http://www.someSchool.edu/someDepartment/picture.gif
    ```
* 網頁瀏覽器 (Web Browser) 為 HTTP 的客戶端，用來發送 **請求 (Request)**，接收並顯示網頁物件
* 網頁伺服器 (Web Server) 為 HTTP 的伺服器端，用來存放物件，並在接受到請求後發送 **回應 (Response)**
![HTTP Request and Respond](https://hackmd.io/_uploads/rJT-qBa1A.png)
* HTTP 使用 TCP 協定，因此 HTTP 訊息一發送，絕對會送到對方手中，也不用擔心順序問題
* HTTP 為 **無狀態的協定 (Stateless Protocol)**，並不會記錄客戶端的狀態
    > 這就是為什麼打開一個網頁用 F12 亂改後，重新整理網頁又會恢復如初

### HTTP Connections
#### 非持續性的連線 Non-persistent HTTP
* 一次 TCP 連線只會傳送一個物件，因此當要下載多個物件時，就需要建立多個連線
* 假設有一個網頁由一個 base HTML file 和 10 個圖片所組成，11 個物件都放在同台主機上， base HTML file 的網址為：
    ```
    http://www.someSchool.edu/someDepartment/home.index
    ```
    那整個傳輸過程就會是：
    1. HTTP 客戶端的程式會要求對 `www.someSchool.edu` 這個主機發起一個 TCP 連線，指定埠號 80
        > 80 為 HTTP 協定預設的埠號
    2. HTTP 伺服器端回復客戶端，同意連接
    3. 客戶端會透過 Socket 送出一個 **HTTP 請求訊息** 到伺服器端，請求包含 `someDepartment/home.index` 這個名稱
    4. 伺服器端收到這則 HTTP 訊息後，就會找出 `someDepartment/home.index` 這個物件，將其封裝為 **HTTP 回應訊息**，再藉由 Socket 送出這則訊息回客戶端
    5. 確認客戶端收到後，伺服器關閉 TCP 連線
    6. 客戶端收到回應訊息，TCP 連線關閉，將回應訊息中的檔案 (HTML) 抽出來，檢查 HTML 檔案，在當中尋找到 10 個圖片的參照
    7. 重複以上的動作直到取得每一個圖片
* 上述的例子中，每傳完一個物件，TCP 連線就會被關閉，因此像這次有 11 個物件要傳，就會建立 11 個 TCP 連線
* **往返時間 (Round-trip Time, RTT)**：封包由客戶端送出抵達伺服器端，再從伺服器端回來所需的時間
* 以這個例子來講，網頁的傳輸大概需要兩個 RTT 外加網頁的傳輸時間
![Non-persistentHTTP](https://hackmd.io/_uploads/SJeCQY6yA.png)
* 缺點：非持續性連線每次傳一個物件就需要一個新的 TCP 連線，而每次傳輸都要耗費兩個 RTT，非常浪費資源，因此才有下面的持續性連線


#### 持續性的連線 Persistent HTTP
* 一個連線可以傳送多個物件
* 可以實現 **管線化 (Pipelining)**

### HTTP Message Format
分為請求訊息和回應訊息
#### HTTP Request Message
HTTP 請求訊息：

```
GET /somedir/page.html HTTP/1.1
Host: www.someschool.edu
Connection: close
User-agent: Mozilla/5.0
Accept-language: fr
```
* 第一行為 **請求行 (Request Line)**，分為三個欄位：
    * 方法欄位：有以下幾種
        * GET 從伺服器傳送資料要求
        * POST 建立或取代伺服器上的資源
        * HEAD 擷取伺服器的 HTTP 回應標頭
        * PUT 更新伺服器上的資源
        * DELETE 從伺服器中刪除資源
    * URL 欄位：要請求一個物件的時候，物件的位址就會寫在 URL 欄位
    * HTTP 版本號欄位
* 第二行以下都是 **標頭行 (Header Lines)
    * `Host: www.someschool.edu`：說名要請求的物件是被放在 `www.someschool.edu` 這個主機上
    * `Connection: close`：回復這個請求後就將連線關閉
    * `User-agent: Mozilla/5.0`：說明是哪種 user agent，也就是甚麼種類的瀏覽器，這個例子中，請求是由 Firefox 發出的
    * `Accept-language: fr`：使用者想看到的語言
![HTTP Request](https://hackmd.io/_uploads/HkqOPFakA.png)

#### HTTP Response Message
```
HTTP/1.1 200 OK
Connection: close
Date: Tue, 18 Aug 2015 15:44:04 GMT
Server: Apache/2.2.3 (CentOS)
Last-Modified: Tue, 18 Aug 2015 15:11:03 GMT
Content-Length: 6821
Content-Type: text/html

(data data data data data ...)
```
* 第一行為 **狀態行 (Status Line)**，有三個欄位
    * 版本號欄位：伺服器使用 HTTP 版本號為 1.1
    * 狀態碼
    * 狀態訊息
    :::info
    * 200 OK：請求成功執行，回應正常回傳
    * 301 Moved Permanently：物件被移動到另一個地方了，新的 URL 會寫在標頭中 `Location:` 欄位
    * 400 Bad Request：當伺服器看不懂請求時會用的錯誤碼
    * 404 Not Found：請求的檔案不在這個伺服器上
    * 505 HTTP Version Not Supported：請求所使用的 HTTP 版本不支援
    :::
* 二到七行為 **標頭行 (Header Lines)**
    * `Connection: close`：告訴客戶端伺服器會把 TCP 連線關掉
    * `Date: Tue, 18 Aug 2015 15:44:04 GMT`：這段回應訊息被送出的時間
    * `Server: Apache/2.2.3 (CentOS)`：伺服器是 Apache 網頁伺服器
    * `Last-Modified: Tue, 18 Aug 2015 15:11:03 GMT`：請求的物件最後被修改的時間
    * `Content-Length: 6821`：送出的物件長度為 6821 位元組
    * `Content-Type: text/html`：送出的物件是個 HTML 文字檔
        > 檔案類型以標頭內的為準，而不是看副檔名

![HTTP Response](https://hackmd.io/_uploads/B1f45KTkR.png)

* 最後面為 **實體主體**
### Cookies
由於 HTTP 伺服器是無狀態的，因此要使用 Cookies 紀錄使用者
![Cookies](https://hackmd.io/_uploads/HkNoiYpJ0.png)
* Cookies 包含四個部分
    1. HTTP 回應訊息中的 cookies 標頭欄位
    2. HTTP 請求訊息中的 cookies 標頭欄位
    3. 由瀏覽器管理的 cookies 檔案
    4. 在伺服器端的資料庫

* 使用者第一次造訪某網站時，伺服器會回傳 **set-cookie** 給瀏覽器，而之後使用者發出請求時，瀏覽器就會將 cookie 加在請求的標頭內，這樣伺服器就認出該使用者

### Web Caching
* **Web 快取**，又稱 **代理伺服器 (Proxy Server)**，可以儲存最近有人存取過的網頁物件副本
* 假如一瀏覽器想請求 `http://www.someschool.edu/campus.gif`：
    1. 瀏覽器建立一個通往代理伺服器的 HTTP 請求，並請求物件
    2. 代理伺服器會先檢查自己有沒有該物件的副本，如果有，直接把物件回應給瀏覽器
    3. 沒有的話就會開啟通往原伺服器的 TCP 連線，並請求物件
    4. 當代理伺服器從原伺服器收到該物件，會先存一份副本在自己這裡，然後將副本回應給瀏覽器
* 由 ISP 購入並安裝
* 優點：
    1. 大幅降低客戶端請求物件所需時間
    2. 減少大型機構的接取網路與網路核心間的流量
    3. 減少 Web 服務在整個網際網路中的流量
* 來看一個範例：
![](https://hackmd.io/_uploads/H1tCwq6kR.png)
* 有兩個網路：大型機構的網路和公用網際網路。機構網路內部傳輸速率為 1 Gbps，機構網路的路由器和網際網路的路由器由一條傳輸速率 1.54 Mbps 的線路連接，假設一個網頁物件的大小為 100K bits，而機構網路中瀏覽器發送 HTTP 請求的平均速度為每秒 15 個請求，RTT (**網際網路延遲**) 為 2 秒，求總回應時間
    > 網際網路延遲 Internet Delay：發出一個請求到收到請求的回應經過的時間
* 總回應時間 (End-end Delay) = 區域網路延遲 (LAN Delay) + 接取網路延遲 (Access Link Delay) + Internet Delay
* 先計算流量強度
    * 區域網路流量強度為：$$15*(100*10^3)/(1*10^9)=0.0015$$
    * 接取網路流量強度為：$$15*(100*10^3)/(1.54*10^6)=0.97$$
* 我們幾乎可以忽略區域網路延遲，但是接收網路的流量強度接近 1，造成的延遲就會很大。那我們該如何解決這個問題
    * 增加接取線路的頻寬，增加至 154 Mbps，這樣流量強度就變成$$15*(100*10^3)/(154*10^6)=0.0097$$但是這是一筆不小的開銷
    * 因此我們可以選擇使用 Web 快取，將其安裝在機構網路裡面，如下圖
![](https://hackmd.io/_uploads/Hkm4yi6kR.png)
* 假設快取的 **命中率 (Hit Rate)** 為 0.4%，則有 40% 的請求可以由快取中取得，大約花費 10 毫秒；而另外 60% 則需要通過接取線路經由網際網路中的原伺服器來滿足
* 因為通過存取線路的流量下降至 60%，因此接取往流量強度會降低為 0.6，而 0.6 時在此線路上延遲已經變成毫秒等級
* 因此我們可以計算：$$d_{end-end-delay}=0.6*2.01+0.4*0.01=1.21secs$$
* 又快又便宜

### The Conditional GET
當伺服器上的檔案被修改時，快取的副本還會是舊版，為了補全這個錯誤，HTTP 有個機制為 **條件請求 (Conditional GET)**
* 滿足條件
    1. 請求方法為 **GET**
    2. 請求的標頭內有一個 `If-Modified-Since:`
* 範例：當一個物件可能被修改過，當有瀏覽器請求這個物件時
    1. 快取會向原伺服器發送請求：
        ```
        GET /fruit/kiwi.gif HTTP/1.1
        Host: www.exotiquecuisine.com
        If-modified-since: Wed, 9 Sep 2015 09:23:24
        ```
        `If-modified-since:` 告訴伺服器檔案如果在這個時間後有被修改，才需要傳檔案過來
    2. 如果檔案沒有被修改，則回應：
        ```
        HTTP/1.1 304 Not Modified
        Date: Sat, 10 Oct 2015 15:39:29
        Server: Apache/1.3.0 (Unix) 

        (empty entity body)
        ```
        狀態為 `304 Not Modified` 告訴快取直接使用你的副本即可
    3. 如果檔案有被修改：
        ```
        HTTP/1.1 200 OK
        .
        .
        .

        data...
        ```
        這時就會用新的檔案將舊的副本覆蓋，接著將副本回應給瀏覽器
        
### HTTP/2
目標：希望降低具有很多物件的 HTTP 請求的延遲
* **HTTP 1.1**：一個 TCP 連線中，有多個且管線化的 GETs (持續性的連線)
    * 伺服器端按照順序依序回應 GET 請求 (**first-come-first-served secheduling, FCFS**)
    * 大物件在傳輸時，小物件就須在大物件後等待 (**head-of-line blocking, HOL**)
    * 萬一有封包丟失，在重傳期間傳輸會暫停
    ![](https://hackmd.io/_uploads/r1jf5E0yC.png)

* **HTTP/2**：降低多物件 HTTP 請求的延遲
    * 請求、回應欄位均與 HTTP1.1 大致相同
    * 由客戶端指定物件的優先度來決定傳輸順序
    * 在客戶端還沒發送特定物件請求前，就先將該物件 **push** 給客戶端
    * 將物件打包成二進位的 **訊框 (frame)**，調度每個訊框減輕 HOL blocking
    ![](https://hackmd.io/_uploads/HkEN5EAJ0.png)
    * 封包丟失時，物件的傳輸還是會暫停
    * 沒有安全性保護
* **HTTP/3**：增加安全性保護、透過 UDP 來實現物件錯誤及壅塞控制

## E-mail
<img src="https://hackmd.io/_uploads/SyAyhNAyA.png" height="500">

* 三大元件
    1. 使用者代理 User Agent, UA
    2. 信件伺服器 Mail Server
    3. 簡單郵件傳輸協定 Simple Main Transfer Protocol, SMTP
    
### 使用者代理 User Agent
* 功能：讀、寫、轉發、儲存信件
* 寄信時，使用者代理會將信寄給信件伺服器
* 當收信時，使用者代理會從伺服器抓取信件

### 信件伺服器 Mail Server
* **信箱 (Mail Box)** 位於信件伺服器中，儲存該使用者收到的信件
* 電子郵件會經過以下路徑：
    1. 寄件人的使用者代理
    2. 寄件人的信箱
    3. 收信人的信件伺服器
    4. 收信人的信箱
* 如果送出的信件沒有成功送達，會被暫存於 **信件隊伍 (Message Queue)**，並稍後嘗試重傳

### 簡單郵件傳輸協定 SMTP
* 規範於 RFC 5321
* 使用 TCP 保證訊息能正確送達
* 埠號通常為 25
* 訊息編碼為 7-bits ASCII
* 假設 Alice 要傳送 Email 給 Bob：
    1. Alice 使用 UA 提供 Bob 的信箱地址 `bob@someschool.edu`，並寫了一封信寄出
    2. Alice 的 UA 將信建送到她的信件伺服器，這封信被放在信件隊伍中
    3. 客戶端的 SMTP 與 Bob 的信件伺服器的伺服器端 SMTP 建立 TCP 連線
    4. SMTP 客戶端將 Alice 的信件送入 TCP
    5. Bob 的信件伺服器上，SMTP 伺服器端收到了信件，將其放入郵箱中
    6. Bob 透過 UA 閱讀信件
    ![](https://hackmd.io/_uploads/ByzB7HAk0.png)
* 特別注意，SMTP 不會使用中介伺服器，就算兩個信件伺服器遠在地球另一端，SMTP 還是會建立一個直通的 TCP 連線，因此如果另一端的信件伺服器未開啟，信件就需一直待在信件隊伍中等待發送

### Comparison with HTTP
* HTTP 為 Pull Protocol：TCP 連線是由收信方建立
* SMTP 為 Push Protocol：TCP 連線是由送信方建立
* SMTP 需使用 7-bits ASCII，如果出現非 7-bits ASCII 的字元，須將其重新編碼為 7-bits ASCII，而 HTTP 不需要
* HTTP 的每個物件單獨使用一個訊息傳送，而 SMTP 則將全部的訊物件放於同一條訊息內傳送

### Mail Message Format
* 規範於 RFC 5322
* 格式：
    * 標頭：
        ```
        From: alice@crepes.fr
        To: bob@hamburger.edu
        Subject: Searching for the meaning of life.
        ```
        > 所有標頭必須包含 `From:` `To:`，而 `Subject:` 不強迫
    * 一行空格
    * 最後為 **實體主體**，只有 ASCII 字元

### 郵件存取協議 Mail Access Protocols
如果說 SMTP 專門用來送郵件，那我們還需要一個協議來讓收信人存取信件
* 郵局協定第 3 版 Post Office Protocol -- Version 3, POP3
    UA 開啟一個通往信件伺服器的 TCP 連線 (埠號 110)，當連線建立完成，執行三階段：
    * 身分認證：UA 必須傳送正確的使用者名稱及密碼
    * 交易：獲取信件、標記刪除信件、移除標記及獲取信件統計資料
    * 更新：在客戶端發出 `quit` 結束 POP3 之後觸發，信件伺服器會刪除標記的信件
* 網際網路資料存取協定 Internet Message Access Protocol, IMAP
    * IMAP 允許使用者在信件伺服器上創建資料夾，使其較方便管理
    * 所有操作都在伺服器上完成，因此不同裝置不會有不同步的問題
    * 允許使用者下載郵件的部分元素

### Web-based Email
* 網頁瀏覽器當作 UA 來使用
* 使用 HTTP 與遠端信箱通訊，讀信寄信都是，但伺服器間還是使用 SMTP

## 網域名稱系統 Domain Name System, DNS
人類喜歡用 **主機名稱 (Hostname)** 來辨認主機 `www.facebook.com`
而路由器偏好 **IP 位址** `157.240.31.35`
因此我們需要一個類似查號台的服務，而這就是 **DNS** 的用處
### DNS
RFC 1034
* 一個由 DNS 伺服器以階層式架構所組成的 **分散式資料庫 (Distributed Database)**
* 一個讓所有主機能夠查詢上述分散式資料庫的應用層協定
* 提供的服務有：
    * 將主機名稱換成 IP 位址
        瀏覽器請求 `www.someschool.edu/index.html` 時，該使用者的機器有 DNS 的客戶端
        1. 瀏覽器會將 `www.someschool.edu` 傳給 DNS 客戶端
        2. DNS 客戶端會發送包含主機名稱的請求到 DNS 伺服器端
        3. DNS 客戶端會收到一個來自 DNS 伺服器的回應，回應中包含對應主機名稱的 IP 地址
        4. 瀏覽器收到 IP 地址，就可以與 HTTP 主機建立 TCP 連線
    * 主機別名 Host Aliasing
        * 假如一個主機名稱太長，我們就可以幫它取別名
        * 而原本的名稱被稱為 **正規主機名稱 (Canonical Hostname)**
        * 別名則稱為 **主機別名 (Aliasing Hostname)**
    * 信件伺服器別名 Mail Server Aliasing
    * 負載分散 Load Distribution
        * 流量大的主機都會有許多 **副本伺服器 (Replicated Web Server)**，擁有不同的 IP 位址
        * 正規主機名稱對應到的是這些副本伺服器 IP 位址的集合
            > DNS 客戶端請求到對應的正規主機名稱，DNS 伺服器會回應整個 IP 地址的集合，並將集合順序輪轉一格。因為瀏覽器使用的都會是集合中的第一個，因此這樣能夠分散流量的效果

### Overview of How DNS Works
####  A Distributed, Hierarchical Database
![](https://hackmd.io/_uploads/rJNu8OA1C.png)
* DNS 伺服器可以分成三類
    * 根域名 DNS 伺服器 Root DNS Server
        * 如果其他 DNS 伺服器無法解析的主機名稱，就會送到這裡來
        * DNSSEC：提供安全性
        * 由 **ICANN (Internet Corporation for Assigned Names and Numbers)** 所管理
    * 頂級域名 DNS 伺服器 Top-level Domain (TLD) DNS Server
        * 所有的頂級域名或是國家域名 `.com` `.org` `.tw` `.jp` 等，都有一個對應的 TLD 伺服器
    * 權威域名 DNS 伺服器 Authoritative DNS Server
        * 想在網際網路上提供公開存取的主機的組織，要提供自己的主機名稱對應到的 IP 位址，權威域名伺服器就是用來存儲這些資訊的
        * 他們可以選擇自行實作權威域名伺服器，或是外包給其他服務商
* 本地 DNS 伺服器 Local DNS Server
    * 不嚴格屬於上面那幾類
    * 每一個 ISP 都有自己專屬的本地伺服器
        > 又稱 **預設域名伺服器 (Default Name Server)**
    * 當有主機送出 DNS 查詢時，會先經過本地伺服器，會由這個機器作為代理，將請求轉發到上面提到的幾種伺服器

![](https://hackmd.io/_uploads/HJuwX9RkA.png)
* 查詢順序範例：假設 `cse.nyu.edu` 想要查詢 `gaia.cs.umass.edu` 的 IP 位址，而本地 DNS 主機名稱為 `dns.nyu.edu` 且負責 `gaia.cs.umass.edu` 的權威域名 DNS 主機名稱為 `dns.umass.edu`
    1. `cse.nyu.edu` 會先往 **本地** 伺服器 `dns.nyu.edu` 送出請求，請求內容包含 `gaia.cs.umass.edu`
    2. **本地** 會將請求轉達至 **根域名** 伺服器
    3. **根域名** 就會根據 `.edu` 而回傳負責 `.edu` 的 **頂級域名** 伺服器列表
    4. **本地** 隨機挑選一個 **TLD** 並將原本的請求發送過去
    5. **TLD** 根據 `umass.edu` 傳回麻薩諸塞大學 (UMASS) 的 **權威域名** 伺服器的 IP 位址 `dns.umass.edu`
    6. **本地** 將請求發到 `dns.umass.edu`
    7. **權威域名** 就會將 `gaia.cs.umass.edu` 的 IP 地址回傳到 **本地**
    8. **本地** 再將結果回傳給 `cse.nyu.edu`
* 以上的例子使用了 **迭代查詢 (Iterative Query)** 與 **遞迴查詢 (Recrusive Query)**
    * 迭代查詢：回應直接傳給請求的主機
        > 「我不知道欸，你可以問他」
        > 上個例子的 (2, 3), (4, 5), (6, 7)
    * 遞迴查詢：被請求的主機幫忙尋問其他主機去找到結果
        > 「我不知道欸，但我可以幫你問」
        > 上個例子的 (1, 8)

#### DNS Cashing
* 每當一個 DNS 伺服器收到一個回應，就可以將其對應表存入自身的記憶體中，下次有人來問就可以直接回答
* 能讓大部分 DNS 請求跳過根域名伺服器

### DNS Records and Messages
DNS 資料庫中，儲存了 **資源紀錄 (Resource Records, RRs)**
* RRs 由四個元組組成：
    ```
    (Name, Value, Type, TTL)
    ```
    > TTL：該紀錄的存活時間，紀錄什麼時候這筆資料要從快取中刪除
    * `Type=A` 時，`Name` 為主機名稱，`Value` 為 IP 位址
    * `Type=NS` 時，`Name` 為網域名稱，`Value` 為該網域的權威域名 DNS 伺服器的主機名稱
    * `Type=CNAME` 時，`Name` 為某個主機的別名，`Value` 為其正規名稱
    * `Type=MX` 時，`Name` 為某信件伺服器的別名，`Value` 為其正規名稱

### DNS Messages
DNS只有兩種訊息：**詢問 (Query)** 及 **回應 (Reply)**，兩者格式一模一樣
![](https://hackmd.io/_uploads/S1FkTqRyA.png)
* 前面 12 Byte 為標頭區段 (Header Section)：
    * 識別碼 (Identification)，為 16-bit 的數字，會被複製到該詢問的回應上，讓客戶端辨別該回應是對應到哪個詢問
    * 旗標欄位 (Flags)，
        * 1-bit 標示訊息是詢問 (0) 或是回應 (1)
        * 1-bit 回應的 DNS 伺服器是權威域名時為 1
        * 1-bit 當客戶端請求希望使用遞迴查詢時設定為 1
        * 1-bit 收到請求的 DNS 主機支持遞迴查詢時，回應時會設定為 1
* 問題區段 (Question Section)
    * 一個 name 欄位，代表所詢問的主機名稱
    * 一個 type 欄位，代表欲查詢的紀錄為哪種類型
* 回答區段 (Answers Section)
    * 包含原本查詢的名字的 RRs
* 權威區段 (Authority Section)
    * 包含其他權威域名伺服器的紀錄
* 備註區段 (Additional Section)
    * 提供有用信息

### Inserting Records into DNS Database
* 域名註冊商 DNS register
    負責驗證域名的獨一性、把域名輸入資料庫
* 例：我們現在要向域名註冊商註冊 `networkutopia.com` 這個網域名稱
    1. 要向註冊商報備主要及次要的權威域名伺服器的主機名稱和 IP 位址
        > 假設主機名稱為`dns1.networkutopia.com` `dns2.networkutopia.com` 
        > 對應的 IP 位址為 `212.212.212.1` `212.212.212.2`
    2. 將以下資訊註冊到 DNS 系統中
        ```
        (networkutopia.com, dns1.networkutopia.com, NS)
        (dns1.networkutopia.com, 212.212.212.1, A)
        ```
        
## Peer-to-peer File Distribution
* 沒有保持開啟的伺服器，只有斷斷續續連線的主機，這些主機我們稱之為 **Peer**
* 相比於主從式有一個固定 IP 的伺服器，P2P 之間都是使用浮動 IP
* P2P 相較主從式架構有更好的 **自擴展性 (Self Scalability)**，每多一個新的 peer，就能帶來更好的服務能力
    * 假設一台伺服器要向大量的主機分享大型檔案，如果使用主從式架構，伺服器就需要親自將每個檔案送到每個主機上，容易造成伺服器的負擔
    * 在這個情況下使用 P2P，每個 peer 都可以把自己手上的檔案分享給其他 peer，而收到的 peer 再將檔案分享給其他 peer，這樣伺服器的負擔就會相對較小
* 舉例來說：假設有個伺服器和 N 個 peers 都透過接取線路連接到網際網路上，現在伺服器要將一份大小為 F bits 的檔案送給所有的 peers，我們將伺服器的上傳速率設為 $u_{s}$，第 $i$ 個 peer 的上傳速率與下載速率分別為 $u_{i}$ 和 $d_{i}$
    * 先來計算主從式架構的傳送時長，將其計為 $D_{cs}$
        * 由於不會有任何 peer 幫忙傳遞，所以伺服器總共要上傳 $NF$ bits，因此上傳需要花費 $NF/u_{s}$ 秒
        * 接下來我們再取得下載最慢的機器會花費多少時間：$F/min\{d_{1}, d_{2}...d_{N}\}=F/d_{min}$ 
        * 考慮以上兩點，我們可以得到：$$D_{cs}\geq max\{\frac{NF}{u_{s}}, \frac{F}{d_{min}}\}$$
        * 我們可以看到，N 越大，所需要花費的時間也會劇烈增加
    * 接下來使用 P2P 的方式，將其計為 $D_{P2P}$
        * 首先，伺服器要先上傳檔案到整個 peers 系統裡面：$F/u_{s}$ 秒
            > 不一定要傳第二次，因為 peers 之間會幫忙傳遞
        * 我們一樣要考慮下載最慢的機器所花的時間：$F/min\{d_{1}, d_{2}...d_{N}\}=F/d_{min}$ 秒
        * 如果我們將整個系統視為一體，則系統的上傳速率會等於伺服器的上傳速率加上所有 peers 的上傳速率，而總共要上傳 $NF$ 個 bits，因此最小傳遞時長為 $NF/(u_{s}+u_{1}+u_{2}+...+u_{N})=NF/u_{s}+\sum_{i=1}^N u_{i}$ 秒
        * 考慮以上三點，我們可以得到：$$D_{P2P}=max\{\frac{F}{u_{s}}, \frac{F}{d_{min}}, \frac{NF}{u_{s}+\sum_{i=1}^N u_{i}}\}$$
![](https://hackmd.io/_uploads/ByX2sTRyC.png)

### BitTorrent
檔案傳輸用的 P2P 協議
* **Torrent**：共同參與傳遞檔案的 peers 的集合
* **Tracker**：用來跟蹤 Torrent 裡面的 peers
* 通常會把一個大檔案拆成一個個 **Chunk**，一個 Chunk一般來說是 256KB
* 簡單來說：
    * 當一個 peer 剛加入一個 torrent 時：
        * 先向 tracker 註冊，並且定期告訴它自己還在裡面
        * 嘗試與所有 peer 建立 TCP 連線，順利連接的 peer 我們稱為 **鄰接 (Neighboring Peers)**
            > 隨著時間經過，會有其他 peers 想要與我們建立 TCP 連線，因此一個鄰接會是浮動的
    * 下載進行中：
        * 每個 peer 都會擁有目標檔案的 chunk，我們會定期向鄰接的 peers 要求他們擁有的 chunk 列表，這樣就知道缺哪個 chunk 要向誰發送請求
            > 通常會 **先拿最稀有的**
        * 當收到請求時，會先優先回覆*提供他資料速率最快的鄰居*
            * 假如說挑出最快的四個鄰居，我們會傳送 chunk 給他們
            * 每 10 秒鐘會重新測一次速率
            * 這些人被稱為 **unchocked**
        * 每隔 30 秒，會隨機選擇一個鄰居並傳送 chunk 給他
            * 我們稱這個人為 **optimistically unchoked**

## Video Streaming and Content Distribution Networks
### Internet Video
* 影片 Video：一連串的照片，以固定的 **幀率 (frame rate)** 進行播放
* **位元速率**：影片位元速率愈高，畫質愈好
    > 100kbps 低畫質
    > 3Mbps 高畫質
### DASH Dynamic, Adaptive Streaming over HTTP
* 伺服器將影片分成一個個資料塊
* **清單檔案 (manifest file)**：記錄每一個資料塊的位置
* 持續監控使用者的流量速度，決定一個適合使用者的檔案 (解析度)

### Content Distribution Network, CDN
我們該如何串流影片同時送給數百萬個使用者？
* 建立一個大型資料中心？
    * 如果客戶端很遠，就會導致延遲
    * 同一個影片可能在一條線路被傳送了很多次
    * 單一資料中心會有單點故障問題
* 因此我們會使用 **內容傳遞網路 (CDN)** 來實現
* CDN 通常會遵循以下兩個原則：
    * Enter Deep：伺服器部屬到世界各地，盡可能接近使用者
    * Bring Home：將伺服器部屬於網際網路交換中心 (IXP)

### CDN Operation
使用者透過瀏覽器請求下載某影片時，CDN 會將請求攔截下來以決定：
1. 使用哪個伺服器來服務這個客戶端
2. 將該請求導向到適合的伺服器