最初に
本記事はネットワークゲームに開発を行う前に知っておくべきであるTCP
とUDP
、RUDP
の違いを勉強し直したものとなります。
TCP?UDP?
IP(Internet Protocol)
の一段階上に当たるトランスポート層の**プロトコル(通信を行う時の取り決め)**として標準的に使われている通信モデルです。どちらもクライアントとサーバ間でのポートの提供と通信管理を行います。
TCPって?
TCPとはTransmission Control Protocol
の略称です。
1対1でコネクションを繋ぐプロトコルで、通信相手の状況を確認をしてから接続を確立したり、データの転送が終わると切断するという手順を踏みます。
TCPの大まかな流れは以下の通りです。
- 受信側がデータを受け取れる状態かどうかを確認してから通信を開始。これを**「通信を確立する」**という。
- データを決められた大きさに分割し、TCPヘッダをつけて順番に送信する。受信側は届いたデータをチェックして受信の連絡を行う。
- データを送り終わったら通信を終了する。
通信を確立する際には**「3wayハンドシェイク」という手順を踏みます。また、相手が確実にデータを受け取ったかどうかの受信確認**を行なったり、データの欠落や破損を検知してデータを再送する機能を持っています。他にも、届いたデータを送信順に並べ直したりといった制御を行います。
そのため信頼性はとても高いですが、負荷が高いため転送効率は低く、通信経路の品質が低いとデータの到着に遅延が生じたり通信不能になりやすいです。転送効率より確実性が重視される用途でよく利用されています(例:www
や電子メール、ファイル転送、HTTP
、SSH
等)。
TCPヘッダ?
データをやり取りする際には、データの受信側に必要となる情報を共通の書式でデータに付け加えています。ここでデータよりも前に付けた情報部分をヘッダ、後に付けた情報部分をトレーラといいます。TCPヘッダの情報を見る事で、受信側は受け取ったデータを順番通りに並べ直します。その後、TCPヘッダを取り除いてからデータを組み直し、アプリケーション層へと渡します。
3wayハンドシェイク
TCPは通信相手の状況を確認をしてから接続を確立していきます。この時に3wayハンドシェイクというやり取りが行われます。TCPヘッダには6ビットのコントロールフラグが含まれており、これが通信相手に通信状況を伝えるために使用されています。通信相手に対して伝えたい項目だけを「1」と設定します。
コントロールフラグ内のビット毎の名前 | 1の時の概要 |
---|---|
URG(Urgent) | セグメントが緊急なデータを含む。 |
ACK(Acknowledgment) | 通信の確認に対して了承。 |
PSH(Push) | セグメントをすぐにアプリケーション層に渡す。 |
RST(Reset) | 通信を強制的に切断。 |
SYN(Synchronize) | 通信の開始を要求。 |
FIN(Fun) | 通信の終了を要求。 |
さて、上記を踏まえた上で、3wayハンドシェイクのステップを見ていきます。
- クライアントがサーバーにSYNパケットを送信(000010)
- サーバーはそれを了承するACKと通信の開始を要求するSYNを一緒に送信(010010)
- クライアントはサーバーに対して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の使い分け
ゲームジャンル | 適するプロトコル |
---|---|
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の違い,深層の真相
- TCPとUDPの特徴をざっくり知る
- ネットワーク ゲームにおけるTCPとUDPの使い分け
- TCP/IPの絵本(書籍)