【ネットワーク】トランスポート層のTCPとUDPの仕組みを理解する

## はじめに
今回は、**TCP/IP**について学んだことをまとめたいと思います！
TCP、IPどちらについてもまとめる予定でしたが長くなったので今回は、TCP（あとUDP)に絞って書きます！


## TCP/IPとは？
**TCP/IP**は、インターネットやネットワーク通信の基礎を支える**プロトコル群**です
このTCP/IPモデルは、ネットワークを支える仕組みとして、主に**4つの階層モデル**で構成されています

## 4つの階層モデル

### 1. アプリケーション層
Webサービスや電子メールなど、ユーザーにサービスを提供するための**機能（プロトコル）**を提供します
**例**：HTTP、FTP、SMTPなど。  
- 例えばQiitaというWebサービスが、記事の閲覧、作成、更新、削除などの機能を提供するために、HTTPプロトコルが使われます

### 2. トランスポート層
データを宛先のアプリケーション(アプリケーション層のプロトコル)に届けるための**機能（プロトコル）**を提供します  
- **TCP**：データの抜け落ちがないように、正確で確実にデータを届ける
- **UDP**：データを高速に届けるが、信頼性は保証されない

### 3. インターネット層
データを宛先の機器(Webサーバやルータなど)まで届けるための**機能（プロトコル）**を提供します
- **IP**：宛先のIPアドレスに基づいて、データを隣接するルーターに転送し、最終的に目的地のネットワーク、機器まで届けます

### 4. ネットワークインターフェース層
データを物理的な信号に変換し、隣接する機器同士にデータを渡す層です
**例**：イーサネット、無線LAN（Wi-Fi）など

この記事ではTCPとUDPが関わるトランスポート層について書きます！

## トランスポート層の役割
データを宛先のアプリケーション(アプリケーション層のプロトコル)に届けることになります
どのアプリケーションに届けるかはポート番号を見て判断します
80番ならHTTPなど

### ポート番号の種類
大きく分けて3種類あります

### 1.システムポート
0~1023番
サーバのプログラムが待ち受けに利用するポート番号

**主要なシステムポート番号**

| **プロトコル**        | **ポート番号** | **説明**                                              |
|-----------------------|----------------|-------------------------------------------------------|
| **HTTP**              | 80             | Webページの表示に使用されるプロトコル（非暗号化）    |
| **HTTPS**             | 443            | SSL/TLSを使った暗号化されたWebページの表示            |
| **FTP**               | 21             | ファイル転送プロトコル（コントロール用）              |
| **SSH**               | 22             | 安全なリモートアクセスやファイル転送                  |
| **SMTP**              | 25             | メール送信プロトコル                                  |
| **DNS**               | 53             | ドメイン名解決のためのプロトコル（UDP/TCP両方使用）  |
| **POP3**              | 110            | メール受信プロトコル（古いプロトコル）                |
| **IMAP**              | 143            | メール受信プロトコル（現在主に使用されるプロトコル） |
| **MySQL**             | 3306           | MySQLデータベースの通信           

### 2.ユーザポート
1023番~49151 番
メーカが割り当てを行い利用するポート
#### 3.ダイナミックポート
49152 ~ 65535 番まで
クライアント側のプログラムが利用するポート
宛先のコンピュータに接続を要求する際に、空いているポート番号が動的にふられる

上記のポート番号と IP アドレスの組み合わせで、相手を識別します

## トランスポート層のプロトコル
トランスポート層にはTCPとUDPの2つのプロトコルがあります
## TCP
TCP は宛先に対して、送るデータ量や受け取れるデータサイズなどを伝え合います
そして届かなかった時は、再送依頼を行うなど、データを確実に相手先に届けるための機能を提供します

### どのようにしてデータを確実に届けるのか？
TCPで扱うデータの単位をセグメントと呼びます
セグメントはデータを確実の届けるために必要なメタ情報を含む、TCPヘッダーと実データの2つで構成されます

#### TCPヘッダーの中身

| フィールド名           | 長さ (ビット) | 説明                                                    |
|------------------------|---------------|---------------------------------------------------------|
| 送信元ポート番号       | 16            | データを送信した側のポート番号                           |
| 宛先ポート番号         | 16            | データの送信先のポート番号                               |
| シーケンス番号         | 32            | 送信側が送ったデータのバイト数を示す番号。データがどこまで送られたかを管理する                         |
| 確認応答番号 (ACK)     | 32            | 受信側が次に受け取りたいデータのシーケンス番号を示す           |
| データオフセット       | 4             | TCPヘッダーの長さを示す                                  |
| コントロールフラグ                 | 8             | 宛先に状況を伝えるためのフラグ（SYN、ACK、FIN など）          |
| ウィンドウサイズ       | 16            | 受信側が受け取れるデータの最大量(バッファのサイズ)                        |
| チェックサム           | 16            | ヘッダーとデータのエラーチェック                         |
| 緊急ポインタ           | 16            | 緊急データの位置                                         |
| オプション             | 可変長        | 特定の状況で使用される追加のオプションフィールド         |
| データ                 | 可変長        | 実際に送信されるデータ部分                               |

これらの情報を使用して、データを届けます

### 相手に状況を伝えるコントロールフラグ
TCPでは現在の自分の状況を伝えるためにコントロールフラグというものを使います
8ビットで構成されていて0か1でオン、オフを表現します

| **フラグ**  | **説明**                                                              |
|-------------|-----------------------------------------------------------------------|
| **SYN**     | 接続開始要求を行うフラグ。セッション確立時に使われる（同期）。           |
| **ACK**     | データを正常に受信したことを確認するための応答フラグ。                  |
| **FIN**     | 接続の終了を要求するフラグ。通信を終了するときに使われる。              |
| **RST**     | 異常な接続をリセット（強制終了）するためのフラグ。                      |
| **PSH**     | データをすぐに受信側に渡すよう指示するフラグ（バッファリングしない）。    |
| **URG**     | 緊急データを示すフラグ。優先的に処理されるべきデータがあることを通知。  |
| **ECE**     | Explicit Congestion Notification (ECN) 対応のフラグ。輻輳（ふくそう）状態を通知する。 |
| **CWR**     | 輻輳ウィンドウが減少されたことを示すフラグ（輻輳通知応答）。            |

### TCP通信の接続確率の流れ
TCP 通信の接続確立 3 ステップかけて確実に行われるので**3-way handshake** と呼ばれます
流れは以下の通りです

1. **クライアント側**：通信を開始するために、SYNのフラグをオンにしてサーバに送信します。この SYN パケットには初期のシーケンス番号（ISN）が含まれます

2. **サーバ側**：SYN を受け取ったサーバは、クライアントに対して ACK（確認応答）フラグとともに自分の SYN フラグをオンにしたパケットを返します。これを**SYN-ACK パケット**と呼びます。サーバ側の初期シーケンス番号も含まれています

3. **クライアント側**：SYN-ACK パケットを受け取ったクライアントは、サーバに対して ACK フラグを持つパケットを返します。この ACK パケットで 3-way handshake が完了し、接続が確立します

通信を確立するときは、お互いの最大セグメントサイズのすり合わせも行います
最大セグメントサイズは MSS(Maximum segment Size)と呼びます
タイミングとしては、クライアント側がはじめに SYN をフラグを ON にして送った際に、クライアント側の**MSS**をオプションフィールドに付与して送る
サーバ側では、送られてきた MSS と自身の MSS を照らし合わせて、小さい方を採用する。
そうして TCP ヘッダーのオプションフィールドの MSS に設定し、SYN-ACK フラグをオンにして返します。
これでMSSが決まります。
MSSとウィンドサイズどう違うの？ってなると思うのですが(自分はそうなりました笑)
MSSはセグメントのデータ部分の大きさを指します。
ウィンドサイズは受け取り側が処理する際に使う、バッファの容量になります。
トランスポート層はTCPから受け取ったデータをまずバッファに置いてからアプリケーション層に渡します。その容量のことです。

### シーケンス番号と確認応答番号
シーケンス番号はデータをどこまで(何Byteまで)送信できたかを示す番号
確認応答番号はデータをどこまで受け取ったか(何Byteまで）を示す番号
これは当然、クライアント側、サーバ側、立場によって変わります

### 例:データ転送中のシーケンス番号と確認応答番号の流れ
**前提条件**
- MSS が 1000 バイト
- クライアント側は 1200 バイトのデータをサーバに送りたい
- サーバ側は 2000 バイトのデータをレスポンスとして返したい
- 接続確立時に設定された初期のシーケンス番号は1とする(実際は、セキュリティ上ランダムで割り当てられるみたいです)

#### 1. クライアントが最初の 1000 バイトを送る
- **クライアント側**：シーケンス番号は**1**。データのうち、最初の 1000 バイトを送信
- **サーバ側**：1000 バイト受信後、次に受信することを期待するバイトは**1001**なので、確認応答番号を**1001**にして、ACK フラグを立てたパケットをクライアントに返す

#### 2. クライアントが残りの 200 バイトを送る

- **クライアント側**：ACK を受け取ったので、シーケンス番号を**1001**にして、残りの**200 バイト**を送信
- **サーバ側**：200 バイトを受信。サーバは次に受信することを期待するシーケンス番号を**1201**にして、ACK フラグを立ててクライアントに返す

#### 3. サーバが 1000 バイトのレスポンスを送る

- **サーバ側**：サーバはシーケンス番号**1**から、最初の 1000 バイトのレスポンスをクライアントに送信
- **クライアント側**：1000 バイトのデータを受信し、次に期待するサーバのシーケンス番号が**1001**であるため、確認応答番号を**1001**にして ACK フラグを返す

#### 4. サーバが残りの 1000 バイトを送る

- **サーバ側**：ACK を受け取ったので、シーケンス番号を**1001**にして、残りの**1000 バイト**をクライアントに送信
- **クライアント側**：残りの 1000 バイトを受信し、次に期待するシーケンス番号が**2001**になるため、確認応答番号を**2001**にして ACK フラグを送信

#### 5. すべての通信が完了

- **クライアント側**：シーケンス番号はそのまま**1201**
- **サーバ側**：確認応答番号は**1201**

このような流れで変化していきます。
シーケンス番号と確認応答番号を見れば、送信したデータ量、受信したデータ量がわかるようになってます！

### TCPによる送信失敗の判断
インターネット上の通信では、ネットワークの混雑や障害によって、パケットが一部届かない、もしくは確認応答（ACK）が送信側に届かないことがあります。送信側はこれを**パケットロス**と見なし、**一定時間（タイムアウト期間）ACK が届かない場合**には、**最後に受信側から確認応答があった時点から再送**を行います

たとえば、最後に受信側から送られてきた確認応答番号（ACK 番号）が**1001**だった場合、送信側は**シーケンス番号 1001 以降のデータ**を再送します。これにより、受信側が正しくデータを受信していない部分だけを再送することができます

### まとめて送って通信を高速化
ここまで聞いて毎回、データを1つずつ送信して、その都度確認応答(ACK)を待つの効率悪くないか？？
と思いますよね(僕は思いました笑)
TCPには、確認応答を待たずにまとめてデータを送信する機能も備わっています
ただ、まとめて送ることでシーケンス番号や確認応答番号がずれることがあるので、まとめて送った時は**同じ確認応答番号が 3 回連続で返ってきた場合**に、パケットロスが発生したと判断してデータの再送を行います！

### まとめて受信できる量を知らせるウィンドウサイズ
このまとめて受信できる量を伝えるために、前述したウィンドサイズが使われます
これは、**受信側のバッファの残容量**を示すものであり、受信側が一度にどれだけのデータを受け取ることができるかを送信側に知らされてます

送信側は、このウィンドウサイズを見て送信するデータの量を調整します。
ウィンドウサイズが大きければ多くのデータを一度に送信、小さい場合は少量のデータを送るみたな感じですね。
この機能がないとバッファの容量を超えるデータを受信し、溢れてしまうようです。
もしバッファが満杯になったら、送信側は一度、送信を止めます。
それからは送信再開のタイミングを知るためにウィンドプロープと呼ばれるパケットを送り、その確認応答でバッファサイズを確認します。

### もしネットワークが混雑していたら
CWR フラグをオンにしてレスポンスを返し、送信側はそれを見て、通信速度を遅くして送る制御をします

### もし途中のパケットだけ抜け落ちた場合
SACKというオプションに抜け落ちたパケットの位置を示す情報を含め、そのオプションにあるデータを再送する

以上がTCPの機能になります

## UDP
**UDP (User Datagram Protocol)** は、データを送るだけの単純なプロトコルになります。動画配信やボイスチャットなどの信憑性や確実性よりも速度(リアルタイム性)を重視したい場面でよく使用されるプロトコルです。

### 特徴
- **通信の確立を待たずにデータを送る**  
  UDP は TCP のように接続を確立するための手続きを省略し、即座にデータを送信します
- **データの一部が抜け落ちてもそのまま送信**  
  途中でパケットが欠落しても再送などの対処はせず、送信を続けます
- **バッファが溢れても対処しない**  
  送信先のバッファがいっぱいの場合でも特に何も制御しません

### UDP ヘッダの構成
- **送信元ポート番号**
- **宛先ポート番号**
- **チェックサム**  
  データが壊れていないか確認するためのフィールドです
- **パケット長**  
  ヘッダの長さとデータの長さを合わせた値です
- **データ本体**

### TCP にはない機能
- **マルチキャスト**  
  1 つのパケットを**複数の特定の相手**に同時に送信する機能
- **ブロードキャスト**  
  1 つのパケットを**ネットワーク内のすべての相手**に送信する機能

### UDPの信頼性はアプリケーション層で補う
UDPは速度を重視するために確実性を犠牲にしています。
ただ、速度を重視しつつデータの確実性や信頼性が必要になる場合もあるので、そんな時は、**アプリケーション層**側で補うアプローチを行うようです。
たとえば
- フロー制御
- 再送処理
- 混雑制御
をアプリケーション側で実装することで速度を維持しながら信頼性を確保するという手立てがあるようです。

## まとめ
今回はトランスポート層のTCPとUDPについて調べたことをまとめました！
普段、特に意識しなくても、インターネット上でデータを送受信したり、動画配信を視聴したりしているけど、その裏にはTCPやUDPがそれぞれ異なる役割でデータを安全かつ効率的に届けてくれているという仕組みがあるのだと知ることができました！

## 参考書籍

https://www.sbcr.jp/product/4815623333/