Unity Engine #2 システム / ネットワーキング
このノートは主にコンピュータシステムとネットワークの知識についてです。
ネットワーク通信の原理
Transmission Control Protocol / TCP
Transmission Control Protocol(TCP)はネットワーク通信プロトコルです。
【基本特徴】
- コネクション指向:データ送信前に、まず接続を確立する必要がある。
- 信頼性のある送信:シーケンス番号、確認応答、再送メカニズムなどを通じてデータの正確な送信を保証する。
- 順序付き送信:データは送信された順序で受信者に届く。
- 輻輳制御:ネットワークの輻輳を防ぐためにデータ送信速度を動的に管理する。
- フロー制御:ウィンドウ機構を通じて送信レートを調整し、受信者の処理が間に合わないことを防ぐ。
【動作原理】
3ウェイハンドシェイク
第1ハンドシェイク:クライアントがサーバーに SYN パケット(seq = x)を送信し、SYN_SENT 状態に入る。
第2ハンドシェイク:サーバーが SYN パケットを受信し、SYN+ACK パケット(seq = y, ack = x+1)で応答し、SYN_RCVD 状態に入る。
第3ハンドシェイク:クライアントが SYN+ACK パケットを受信し、ACK パケット(ack = y+1)を送信し、ESTABLISHED 状態に入る。
4ウェイハンドシェイク
第1ウェーブ:開始者が FIN(seq = u)パケットを送信し、切断を要求する。
第2ウェーブ:受信者が FIN パケットを確認し、ACK(seq = v, ack = u+1)パケットを送信する。
第3ウェーブ:受信者が FIN(seq = w, ack = u+1)パケットを送信する。
第4ウェーブ:開始者が FIN パケットを確認し、ACK(seq = u+1, ack = w+1)パケットを送信する。
TCP ヘッダー構造
TCP ヘッダー(TCP Header)は合計 20 バイト。その中で
- 送信元ポート(Source Port):16 ビット = 2 バイト、対応する型は short。
- 宛先ポート(Destination Port):16 ビット = 2 バイト、対応する型は short。
- シーケンス番号(Sequence Number):32 ビット = 4 バイト、対応する型は uint。
- 確認番号(Acknowledge Number):32 ビット = 4 バイト、対応する型は uint。ACK=1 のときのみ確認番号フィールドは有効。ACK=0 のとき、確認番号は無効。
- データオフセット(Header Length)+ 予約ビット(Reserved)+ 制御ビット(Code Bits):4+6+6 = 16 ビット = 2 バイト。これら3つのデータは合計されて short に格納されるため、計算時はビット演算を使用する必要がある。
注:制御ビット:UAPRSF はそれぞれ URG 緊急パケット/ACK 確認パケット/RST リセットパケット/SYN 同期パケット/FIN 終了パケットに対応。
- ウィンドウサイズ(Window):16 ビット = 2 バイト、対応する型は short。ウィンドウフィールドは相手の送信データ量を制御するために使用され、バイト単位。つまりウィンドウサイズは 0~65535 バイトの範囲のみ。
- チェックサム(Checksum):16 ビット = 2 バイト、対応する型は short。
- 緊急ポインタ(Urgent):16 ビット = 2 バイト。URG = 1(上記の制御ビット)のとき、緊急ポインタフィールドが有効。このセグメントに緊急データがあり、できるだけ早く送信すべきであることをシステムに伝える(高優先度データに相当)。
合計 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 = 20 バイト。
User Datagram Protocol / UDP
User Datagram Protocol(UDP)はもう一つのネットワーク通信プロトコルです。
-
コネクションレス:データ送信前に接続を確立する必要がない。
-
信頼性のない送信:データの確実な到達を保証せず、再送メカニズムもない。
-
順序不定の送信:データが受信者に届く順序は固定されていない。
-
輻輳制御なし:データ送信速度を管理できず、ネットワークの輻輳につながる可能性がある。
-
フロー制御:パケットヘッダー情報が少なく処理速度が速い。
-
データ送信:データを直接送信し、相手が受信できることを保証しない。
-
データ受信:データを受信する際に相手に確認する必要がなく、直接データ処理を開始する。
【UDP ヘッダー構造】
8 バイトのみ。
TCP と同様に、送信元ポートと宛先ポートはそれぞれ 2 バイトを占有。チェックサムと長さはそれぞれ 2 バイトを占有。以下が UDP データなので、ヘッダーは非常に小さい。
【TCP との比較】
切断・再接続メカニズム
切断・再接続メカニズムが必要なほとんどのアプリケーションでは、組み込みの信頼性のある送信メカニズムが設計を簡素化できるため、TCP がより適切な選択です。2つの切断・再接続メカニズムは以下のように設計できます。
参考文献:
- TCP/IP パケット構造の詳細解説:https://www.cnblogs.com/larry-luo/p/10983633.html
TCP 切断・再接続
- 接続状態のチェック:クライアントとサーバーの両方が現在の接続状態を検出するメカニズムが必要。定期的にハートビートメッセージを送信して接続がまだアクティブかどうかをチェックできる。
- 切断の識別:ハートビート検出が失敗したとき、または TCP 接続でエラーが発生したとき、クライアントは「切断」状態として識別すべき。サーバーもクライアントの切断を検出し、クライアントを非アクティブまたは切断としてマークする必要がある。
- 状態の保存:切断が発生したとき、サーバーはクライアントの現在の状態を保存する必要がある。状態情報にはプレイヤーの位置、スコア、アイテムなどが含まれる。
- 再接続の試行:切断を検出した後、クライアントはサーバーへの再接続を試みるべき。再接続試行の時間間隔と最大試行回数を設定できる。
- 認証と状態復元:再接続時、クライアントはサーバーに認証情報を送信する必要がある。サーバーがクライアントの身元を検証した後、クライアントの以前の状態をクライアントに復元する。
- セッションの再開:再接続が成功し状態が復元されると、クライアントは切断前の状態から続行できる。
- 再接続試行の失敗処理:再接続試行が失敗した場合、クライアントはユーザーにプロンプトを表示し、再試行または終了のオプションを提供できる。
UDP 切断・再接続
1. 接続識別とハートビートメカニズム
- 一意の接続識別子(セッション ID など)を使用してクライアントを識別する。
- ハートビートメカニズムを実装して接続のアクティブ状態を監視する。
2. 切断の検出
- クライアントとサーバーが定期的にハートビートパケットを送信する。
- 特定の期間内に相手のハートビートを受信しない場合、接続は切断されたとみなす。
3. 状態の保存
- サーバーはゲームの進行状況、位置などのクライアントの重要な状態情報を保存すべき。
- 状態情報は定期的に更新し、切断中も保持する。
4. 再接続の試行
- 切断を検出した後、クライアントは接続要求を再送信することを試みるべき。
- 再接続要求には以前のセッション ID と最後に知られている状態情報を含めることができる。
5. サーバー側の再接続処理
- サーバーが再接続要求を受信した後、セッション ID をチェックする。
- セッション ID が有効な場合、サーバーは保存された状態情報を使用してセッションを再開する。
6. データ同期
- 再接続が成功すると、サーバーはクライアントの状態を最新の状態に更新する必要がある。
- クライアントも切断から再接続への状態変更を処理する必要がある。
7. フォールトトレランスとデータの一貫性
- 切断中に失われる可能性のあるデータを処理するメカニズムを実装する。
- クライアントとサーバー間のデータの一貫性を維持することが重要。
8. 再接続失敗の処理
- 再接続が失敗した場合(例:最大試行回数を超えた)、ユーザーフィードバックを提供し、再接続または終了のオプションを提供する。
注意事項
- セキュリティと認証:再接続時の認証とデータセキュリティを確保し、詐欺やセッションハイジャックを防ぐ。
- パフォーマンスと最適化:再接続メカニズムが通常のネットワークパフォーマンスに悪影響を与えないことを確保する。
- ユーザー体験:再接続メカニズムを設計する際、ユーザー体験を考慮し、プロセスができるだけスムーズで透明であることを確保する。
UDP 自体のコネクションレスで信頼性のない特性のため、切断・再接続メカニズムを設計する際、接続の安定性とデータの一貫性を確保するためにアプリケーション層でより多くの作業を投入する必要がある。これには、接続状態、データ同期、例外の処理を含む複雑なロジックがしばしば関わる。