ネトゲや配信で使い分けられてるTCPとUDP、RUDPの概念から勉強し直してみた

# 最初に

本記事はネットワークゲームに開発を行う前に知っておくべきである`TCP`と`UDP`、`RUDP`の違いを勉強し直したものとなります。

# TCP？UDP？

`IP(Internet Protocol)`の一段階上に当たるトランスポート層の**プロトコル(通信を行う時の取り決め)**として標準的に使われている通信モデルです。どちらもクライアントとサーバ間でのポートの提供と通信管理を行います。

# TCPって？

TCPとは`Transmission Control Protocol`の略称です。

**1対1でコネクションを繋ぐプロトコルで、通信相手の状況を確認をしてから接続を確立したり、データの転送が終わると切断するという手順を踏みます**。

TCPの大まかな流れは以下の通りです。

1. 受信側がデータを受け取れる状態かどうかを確認してから通信を開始。これを**「通信を確立する」**という。
2. データを決められた大きさに分割し、TCPヘッダをつけて順番に送信する。受信側は届いたデータをチェックして受信の連絡を行う。
3. データを送り終わったら通信を終了する。

通信を確立する際には**「3wayハンドシェイク」**という手順を踏みます。また、相手が確実にデータを受け取ったかどうかの**受信確認**を行なったり、**データの欠落や破損を検知してデータを再送する機能**を持っています。他にも、**届いたデータを送信順に並べ直したり**といった制御を行います。

そのため**信頼性はとても高い**ですが、負荷が高いため**転送効率は低く**、通信経路の品質が低いとデータの到着に遅延が生じたり通信不能になりやすいです。転送効率より**確実性が重視される用途**でよく利用されています（例：`www`や電子メール、ファイル転送、`HTTP`、`SSH`等)。

## TCPヘッダ？

データをやり取りする際には、**データの受信側に必要となる情報**を共通の書式でデータに付け加えています。ここでデータよりも前に付けた情報部分を**ヘッダ**、後に付けた情報部分を**トレーラ**といいます。TCPヘッダの情報を見る事で、受信側は受け取ったデータを順番通りに並べ直します。その後、TCPヘッダを取り除いてからデータを組み直し、アプリケーション層へと渡します。

## 3wayハンドシェイク

TCPは通信相手の状況を確認をしてから接続を確立していきます。この時に**3wayハンドシェイク**というやり取りが行われます。TCPヘッダには**6ビットのコントロールフラグ**が含まれており、これが通信相手に通信状況を伝えるために使用されています。通信相手に対して伝えたい項目だけを「1」と設定します。

|コントロールフラグ内のビット毎の名前|１の時の概要|
|----|----|
|URG(Urgent)|セグメントが緊急なデータを含む。|
|ACK(Acknowledgment)|**通信の確認に対して了承。**|
|PSH(Push)|セグメントをすぐにアプリケーション層に渡す。|
|RST(Reset)|**通信を強制的に切断。**|
|SYN(Synchronize)|**通信の開始を要求。**|
|FIN(Fun)|**通信の終了を要求。**|

さて、上記を踏まえた上で、3wayハンドシェイクのステップを見ていきます。

1. クライアントがサーバーにSYNパケットを送信(000010)
2. サーバーはそれを了承するACKと通信の開始を要求するSYNを一緒に送信(010010)
3. クライアントはサーバーに対してACKを返す(010000)

これで1対1の通信を確立し、その後データのやりとりが開始されます。ちなみに切断するときもコントロールフラグを利用して連絡を取り合います。

## 実際の通信を始める前に

コネクションを確立した後には、実際に通信を始める前に**お互いが扱える以下のデータ量**を確認します。

- ヘッダを含めたデータの大きさ(**セグメントサイズ**)
- 一度に受け取れるデータの数(**ウィンドウサイズ**)

上記は送信側、受信側問わず**サイズの数字が小さい方にもう片方が合わせる**形となります。

## データを確実に届けるための仕組み

TCPでは、**データを届けている途中でデータが破損してエラーとなったり、ネットワークの混雑で通信遅延が起きていたとしても、確実にデータを届けるための仕組み**が用意されています。その中から代表的な3つの機能を紹介します。

### 再送制御

送信の途中でセグメントが行方不明になってしまった場合に、受信側はデータを受け取れません。その場合受信確認の応答はできません。

また、ヘッダ情報としてデータが破損していることを示すチェックサムという値がありますが、その値でデータが壊れてしまっている場合も受信側は受信確認の応答は送りません。

**送信側は受信確認の応答が届かない場合はデータの再送を行います**。

途中で確認応答そのものが行方不明になる場合もあります。その場合もデータの再送は行われますが、**受信側で重複したデータは一つを残して破棄します**。

こういった処理のことを**再送制御**と呼びます。

### ウィンドウ制御

セグメントを一つずつ送るよりも、いくつかまとめて送る方が効率的となります。先ほど**データ通信を開始する前に決めたウィンドウサイズまでであれば、自分で送る量を設定してまとめて送信**することができます。それに対して一つの受信確認フラグを受け取ります。

こういった処理のことを**ウィンドウ制御**と呼びます。

### フロー制御

ウィンドウサイズは通信の途中で変更できます。ネットワークが混んでいる時や、たくさんのデータが届き受信側の負荷が高くなって処理しきれない時は、**送信側に送信するデータを減らす情報＋送れるウィンドウサイズを伝えます**。

例えば、ここで「0」と伝えれば、今は新しいデータを送らないでほしいと送信側に伝えることができます。

ネットワークが空いたり、受信側の負荷が軽くなってきたら再びウィンドウサイズを大きくして、その値を送信側に伝えます。

こうして、**状況に応じてウィンドウサイズを調節する処理のことをフロー制御**と呼びます。



#UDPとは？

UDPとは`User Datagram Protocol`の略称です。

**コネクションレスのプロトコル**で、TCPのように受信確認や再送制御などは行わず、**一方的にデータを送りっぱなしにする仕組み**となります。そのため、ヘッダも小さくなり、**データの確実性よりもリアルタイム性や転送効率を重視する際にはUDPを使用します**（例：音声のストリーミングサービス、IP電話、NTP等）。

## UDPの送信手法

UDPは1対1でデータ送信を行うだけではなく、複数の相手へ同時にデータを送信できます。

特定の複数人に送ることを**マルチキャスト**、不特定多数に送ることを**ブロードキャスト**といいます。

# 二つの比較まとめ

**TCP**
- 信頼性が高い
- コネクション型プロトコルである
- ウインドウ制御，再送制御などを行う
- 比較的低速

**UDP**
- コネクションレス型プロトコル
- 信頼性が低い
- 処理が簡単で遅延が少ない
- 一対多
- 高速でリアルタイム性がある

# RUDP

UDPにTCPの機能を一部追加して、**Reliable(信頼できる)UDPとしたプロトコルの総称**を指します。

RUDPには、**信頼性が必要なデータであれば再送を行いますが、そうでない場合は再送しません**。

信頼性が必要な例：
- ログイン/ログアウト
- マッチング
- アイテム取得　など

信頼性が不必要な例：
- キャラクターの位置更新
- エフェクト
- ボイスチャット　など

ネットワークエンジンのPhotonやモノビットエンジンではRUDPに対応してオン/オフ切り替えられたりするらしいです。

# ゲーム開発においての向き不向き

以下のスライドを参考にしました。
[ネットワーク ゲームにおけるTCPとUDPの使い分け](https://www.slideshare.net/yhonjo/tcpudp-81497235?qid=2262205d-4dcd-430a-85d6-a000417fc30c&v=&b=&from_search=1)

|ゲームジャンル|適するプロトコル|
|----|-----|
|FPS|UDP+RUDP|
|格ゲー(1vs1)|UDP+RUDP|
|格ゲー（複数対戦）|UDP+RUDP|
|レースゲーム(PvP)|UDP+RUDP|
|VR空間共有|UDP+RUDPかTCP|
|RTS/MOBA|UDP+RUDP|
|TPS|RUDPかTCP|
|スマホアクション|RUDPかTCP|
|ボイチャ|RUDPかTCP|
|ストラテジー系|RUDPかTCP|
|MMORPG|RUDPかTCP|
|スマホターン性|TCP|



# 参考

- [第7回　TCPとUDPの違い，深層の真相](http://gihyo.jp/admin/serial/01/net_prac_tech/0007)
- [TCPとUDPの特徴をざっくり知る](https://mrsekut.site/?p=3111)
- [ネットワーク ゲームにおけるTCPとUDPの使い分け](https://www.slideshare.net/yhonjo/tcpudp-81497235?qid=2262205d-4dcd-430a-85d6-a000417fc30c&v=&b=&from_search=1)
- TCP/IPの絵本（書籍）