前置きなど 全般 負荷・帯域を減らす超基本 ネットワーク基本 サーバ設計 クライアント設計 ネットワーク通信量 ゲームシステム設計 同期の問題 セキュリティ テスト・デバッグ プログラミングテクニック

ネットワーク基本

up
down

TCP?UDP?

 まず、通信をTCPでやるかUDPでやるか、ということについて。
 一般的なコト言うと、TCPは信頼性が高く、UDPはオーバーヘッドが少ないと言われてます。 個人的にはMMOでも大抵の場合TCPでOKだと思います。
 MMOの場合ショートパケットを多く送信することになりがちですので、 ヘッダが短いUDPは正直かなりの魅力です。 また、UDPでも再送信機構など作って信頼性を持たせることも可能でしょう。
 それでもおいらがTCPを推す理由は、ユーザー側の負担が少ないからです。 TCPですと、ユーザー側の負担がかなり低いと思います。 ファイアーウォールなどであえて遮断しない限り、大抵セッションが確立できます。
 UDPの場合は、UDPホール・パンチングが動作すれば、 ユーザーが何も設定しなくともうまく動作するかもしれません。 そうでなかった場合にはUPnPでなんとかして...。 それでもダメなら、ユーザーにルーターの設定をしてもらう必要があります。 それでもダメな場合もあります。
 UDPの場合TCPに比べると、ユーザーが遊べない可能性が高くなりますので、 多くの人に遊んでもらいたいと思うなら、なるべく避けるべきだと思います。
 もし、UDPを使用したい場合には、UDPが使えない場合はTCPで接続する、 みたいにするのが理想だと思います。

 このドキュメントでは特に言及しないかぎり、TCP接続で通信を行う場合の話をします。

 ちなみにmmo!、sandbox(仮)共にTCP接続を使っています。 ただし、mmo!のボイスチャットについてはUDPのP2Pでやってます。
up
down

上りと下り

 MMOの通信、クライアント→サーバ と サーバ→クライアント、 どっちの通信量が多いでしょうか?
 よほど特殊な場合を除いて、サーバ→クライアントの方が かなり通信量が多くなります。

上りと下りの通信  右図を見てください。
プレイヤーのAさんが移動やチャットなどのなんらかのアクションをした場合、 そのメッセージがAさんのクライアントからサーバに送られます。 サーバはB・C・Dさんの3人に「Aさんがアクションをした」というメッセージを送ります。
 実際に何倍程度になるかは、プレイヤーがどの程度密集しているか、 ということに依存しますが、サーバ→クライアントの方が通信量は相当多くなります。
 また、サーバがコントロールするモンスターやNPCがいる場合には、 そのアクションは、サーバ→クライアントの通信のみ発生させますので、その分も多くなります。

 個人が自宅でゲームサーバを稼働させる場合を考えると、 大抵の場合は上下の帯域は同じくらいか、ADSLなどでは上りが帯域が少ないと思います。
 なので、ネットワーク帯域がボトルネックになる場合には、 上り(サーバ→クライアント)が問題になります。
 ネットワーク帯域を制限内に納めるための最適化は、 主にサーバ→クライアントで行うことになるでしょう。
 通信量の問題については「ネットワーク通信量」のページで詳しく説明します。
up
down

ネットワーク処理のI/O戦略

 ネットワークのソケットはいろんなI/Oの方法があります。 簡単に言うと接続や送受信で待ちが発生する場合にどんな方法で待つか、ということです。
 とりあえずWindowsの場合を書きます。
  • ブロック型ソケット
  • 純非ブロック型ソケット
  • 非同期型ソケット(ウインドウメッセージ利用)
  • select使用
  • イベントオブジェクト
  • オーバーラップI/O
  • I/O完了ポート(IOCP)
 http://www.kt.rim.or.jp/~ksk/wskfaq-ja/articles/io-strategies.html
 あたりを参考にしてください。

 まず、クライアントについては、ほとんどの場合 非同期型ソケットでOKでしょう。
 クライアントの場合、セッションは1つとか2つでしょうから、 ネットワーク処理の負荷が問題になることは無いので、使い勝手の良さが第一条件になります。
 クライアントはウインドウを持つだろうから、 ウインドウメッセージとしてソケットイベントが飛んでくるのは処理しやすいです。
 あと、重要なのは、シングルスレッドで処理できるトコロです。 (マルチスレッドプログラミングは非常に奥が深く、 「まともな」コードを書こうと思ったら、かなり気を遣う作業になります。 シングルスレッドでできる処理はシングルスレッドでやりましょう。)

 サーバについては、腕に自信があれば効率が最も高いI/O完了ポートで。 オーバーラップI/Oも悪くないです。
 サーバの場合、ウインドウが存在しないかもしれないし、 Linuxなど他のOSと可能なかぎりコードを共通化したいかもしれないので、 非同期型ソケットはあまり向かないのですが、 使い慣れてる人なら割り切って使うのもアリかも...。 I/O完了ポート・オーバーラップI/Oには効率で及ばないですが。

 linuxでサーバを作る場合にはepollで良いと思います。 linuxでクライアントは...よくわかんないです...フレーム単位で処理するだろうから純非ブロック型ソケットでもいいかな...

 ちなみにmmo!のサーバでは非同期ソケットを、sandbox(仮)のサーバではI/O完了ポートを使用しています。 クライアントはどっちも非同期型ソケットです。
up
down

メッセージの構造

 通信でやりとりするメッセージの構造は、 ゲームシステムにあわせて実装してください。
クライアントがテキストデータしか扱えない、とかいうのでなければ、 バイナリ形式のデータで良いでしょう。
 おいらは基本的な構造として、最初にメッセージのサイズ、 次にメッセージの種類があり、以降はメッセージによって変わります。
 TCPの場合、送信されたデータは複数のパケットに分かれる可能性が常にあります (まとめられる可能性もあります)。 なので、パケットが届いたとしても、メッセージの最初の方だけ先に届いて、 まだ処理できない状態かもしれません。 1つのメッセージが全部届いたかどうかを高速に確認するために、 最初にメッセージのサイズを入れた方が良いでしょう。

 実際の通信では以上のメッセージを暗号化して送受信しています。 暗号化についてはセキュリティのページで説明する予定です。
前置きなど 全般 負荷・帯域を減らす超基本 ネットワーク基本 サーバ設計 クライアント設計 ネットワーク通信量 ゲームシステム設計 同期の問題 セキュリティ テスト・デバッグ プログラミングテクニック
footer
footerページ先頭上の項目前ページ次ページtop
footer