---
# System prepended metadata

title: 傳輸層通訊協議

---

# 傳輸層通訊協議

## 傳輸層協議預期具有的特色

#### 傳輸曾希望達到 的 **理想**

* **保證**訊息傳遞 (可靠傳輸)
* 訊息傳遞順序**不變**
* 一個訊息最多傳一份
* **任意**訊息大小
* 支援發送者與接收者的**同步**
* 允許接收者對發送者執行流量控制
* 支援一台主機上執行多個不同應用程式

#### 傳輸層之下的現實 (IP網路)
* 丟棄訊息
* 重新排序訊息
* 傳遞多份相同訊息
* 傳遞的訊息有大小限制
* 訊息傳遞可能有任意長短的時間延遲

:::info
所以很不可靠
:::
## 簡易反多工協議(UDP)

* demultiplexing 讓在同一個主機上的多個應用可以共享網路。

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

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

## 可靠位組元組串流協議(TCP)

Transmission Control Protocol 提供
*  可靠的服務 (Reliable)
*  連線導向(Connection oriented)
*  字元組串流服務(byte-stream service)

#### 流量控制(Flow control)
因為一個client 上可能有多個應用，但是資料不可能即時處理，所以會先放在queue裡面。
當queue快爆炸得時候，會用這個機制去讓 sender 送慢一點，預防發送者傳送過多，的流量使接收者超出可負荷的容量

:::warning
receiver只告訴 sender 自己的buffer 中剩下多少**量**(byte) ，要用幾個封包去填滿它不是關心的重點。
:::
* 封包滿了就叫sender 不要送

#### 壅塞控制(Congestion control) 
用來預防網路被注 入過多的資料而造成路由器/交換器或鏈路超出負荷

* TCP 需要一個機制讓發送端得知網路的負荷量

#### End-to-end 
* TCP run **over the Internet**，非於一個點對點的鏈結上
* Sliding windows 須考慮：
    * 支援 互聯網上不同主機間建立邏輯連線(logical connections)
    * 不同TCP連線的 RTT 可能差異過大
    * 封包充新排序


### TCP Segment 
* 傳送端將若干位元組寫入一個 TCP連線，接收 端則從該 TCP 連線讀取位元組

因為 header 本身也是有大小的，所以如果data太小，很浪費頻寬


TCP 傳送端將應用程式傳送的位元組先儲存起 來, 等位元組數量形成一個合理大小的資料段 ，再將此資料段送至 TCP 的目的端主機

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

:::info
sneder 每次送一些bytes string 下去，reciver 每次收一些bytes string 上來，而TCP 不管下層是如何切割以及封裝這些bytes string 。
:::

### TCP Header 
![](https://i.imgur.com/XpdgKK7.png)

:::danger
Source 以及 Destination 的 IP adderss 是寫在 IP header 裡面 
:::

#### SrcPort
* 源端口號(source port)
#### DstPort
* 目的端口號(destination port)

#### Acknowledgment

#### SequenceNum:
* 而SequenceNum 欄位為此資料段上的第一個 資料位元組的序號
:::info
之前再講滑動視窗演算法中的 Seqnum 是layer two 對於每一個 package 的編號，
但是因為TCP是 byte-stream 所以他的編號會細緻到對每個byte 做編號。
:::

:::info
Acknowledgment , SequenceNum 都是32bit
:::

#### Flag:
![](https://i.imgur.com/vrxxtWP.png)
* 6-位元旗標欄位用來傳遞 TCP 連線兩端之間的控制訊息
    * **FIN**、**SYN** 結束連線
    * **ACK**
        * 1 Acknowledgment 是有意義的
        * 0 Acknowledgment 無意義
    * **RST** 用來偵測連線是不是異常，用來強制清除一個連線
    * **PSH** 強制送出 Buffer 的所有內容
    * **URG** 這個封包裡面有警急資料
    * **RESET** 接收端想要中止此連線

:::info
URG=1 他會去看Urgent Pointer 指到data 中的哪個位置，此位置之前的都是警急資料。
:::
    
#### Advertised Windows 

65532 bits = 64kb

#### Checksum 
* 檢查碼欄位，TCP Header、TCP data 與 pseudoheader 算出

* pseudoheader 組成
    * 標頭的 Source IP 位址
    * 標頭的 Destination IP 位址
    * length of IP header 

## TCP 連線管理

* 交換資料段之前會先建立 **連線**

* TCP 連線初始變數:
    * 序號
    * 緩衝器, 流量控制訊息 (e.g. RcvWindow)

由client 提出連線需求。

### 連線
* Client: 連線啟動者，利用一個socket 去建立連線
* Server: 等待 client 接觸，建立一個welcom socket 等待client 連線

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

:::info
教學：
[三向交握](http://c.biancheng.net/cpp/html/3042.html) (我覺得不錯的)
[數據傳輸](http://c.biancheng.net/cpp/html/3046.html)
[四次握手斷開連線](http://c.biancheng.net/cpp/html/3043.html)
:::

### 斷線
![](https://i.imgur.com/72ugPh6.png)

:::warning
client 在傳送完最後一個ACK後等帶30s 的Time wait ，去讓還在網路上跑得封包結束傳輸。
server 只要收到那個ACK就可以關閉 connection 了
:::

### Client 狀態圖

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

### Server 狀態圖

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


## 重送 time out



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

### 原始方法
紀錄近幾次的rtt值，做平滑計算
$SRTT_t = \alpha*SRTT_{t-1} + (1-\alpha)*RTT$ , ($\alpha =$ 0.8 ~ 0.9)
$TimeOut = 2 * SRTT_t$

如果我們單純只用送出的時間以及ACK回來的時間差來計算RTT，已左邊的case來看，我們會把重送的封包當成原本封包回來得ACK 而誤判了RTT。

若是右邊這個case 我們可能因為client 的 ACK delate ，因此server重送。
但是當原本的ACK回來時就讓我們誤判了RTT


### Karn/Partidge
* 重新傳輸時**不計算 RTT 值**
* 在每次**重送**之後 **逾時器值加倍**
* 無法解決壅塞問題

### Jacobson/Karels
* 可以除理RTT變異化大的狀況
$SRTT_t = SRTT_{t-1}+α(RTT–SRTT_{t-1})$
$DevRTT_t = ( 1-β ) * DevRTT_{t-1} + β * ( | RTT - SRTT_{t-1} | )$ （計算差距）
$RTO= SRTT + 4*DevRTT$

### TCP 快速重送
* 重複回覆
    * 接收端收到封包，皆回傳一個回覆序號，即使此序號已經回覆過
    * 當傳送端收到重複回覆，它得知另一端一定是接收到非以原先發送順序抵達的封包
* 當server連續三次收到重複的回覆，TCP 會重送該封包

## 壅塞控制
*  TCP壅塞控制的概念是讓每個**傳送端決定目前網路有多大容量**，以便知道自己可以同時傳送多少 封包
*  TCP被稱為**自我時序調節(self-clocking)** ，也就是**透過 ACKs 來調節封包傳輸的節奏**

#### 壅塞判斷
* 發生 **封包遺失**
* TCP傳送端收到三個 **重複回覆**
*  TCP 傳送端發生 **逾時事件**

### 線性增加倍數減少法 AIMD
[例子](https://blog.csdn.net/guo_jia_liang/article/details/53064427)
* 每經過一個RTT 增量一個封包，直到丟失
*  Additive Increase Multiplicative Decrease
*  壅塞視窗 CongestionWindow : 在收到確認 (ACK) 之前，可以發送到網絡中的資料量的 傳送端限制
*  傳送端 可傳送的資料量 ： min(接收端的接收視窗, 壅塞視窗)
*  如何決定『壅塞視窗』的值？ TCP 觀察網路得知
    *  封包遺失(收到三個重複回覆) 視為壅塞的訊號，然後減低傳輸速率
    *  封包遺失，傳送端便將壅塞視窗值減半
    *  CongestionWindow值不可小於單一封包的最大值（也就是資料段最大值maximum segment size (MSS)）
    *  當網路有新增的容量(壅塞減輕),可增加CongestionWindow值（用加的）
    *  $Increment = MSS ×(MSS/CongestionWindow)$
    *  $CongestionWindow+=  Increment$

:::info
每當傳送端成功送出數量等於 CongestionWindow 值的封包 (所有在上一個 RTT 期間傳送的封包都成功收到回覆)，便將CongestionWindow 值加上MSS值
:::

### 慢啟動
和前面一樣，TCP 傳送端收到一個封包的回覆時，將雍塞視窗的值加上 MSS 值
* 探測網路的容量極限
* 以**指數**方式增加CongestionWindow，直到封包首次遺失（以每次收到ACK就增加）
* 傳送端每經過一個RTT 時間封包就傳送**兩倍**的封包數量

### Case 
* 傳送端收到三個重複回覆
    * 網路雖然雍塞, 但還可以傳送一些封包
    * $CongestionWindow = \dfrac{CongestionWindow}{2}$
* 逾時
    * 網路雍塞嚴重！！
    * $CongestionWindow = 1 MSS$

## TCP 吞吐量
* 忽略慢啟動期間
* W 為封包遺失發生時的CongWin值，當時吞吐量為$\dfrac{W}{RTT}$
* 封包遺失後，CongWin值減為$\dfrac{W}{2}$，吞吐量則減為$\dfrac{W}{2RTT}$
* 平均吞吐量: $\dfrac{0.75W}{RTT}$