9

最初に少しコンテキスト:私はScala(ファーストパーソンシューティングゲームのような)でクライアント/サーバーゲームを書いています。クライアントは1秒間に数十回サーバーに移動の意図を送信する必要があり、サーバーはエンティティの状態を送り返します。リアルタイムでも。クライアント側(グラフィカルな流動性のため)とサーバー側の両方でJBulletを使用して、これらのエンティティの物理シミュレーションがあります。クライアントがサーバーから更新を受信するたびに、クライアントはそのローカル状態をサーバーが送信した状態に置き換えます。もちろん、特定の瞬間に同じサーバー上に多くのクライアントが存在する可能性があります。要するに、このアプリケーションでは、通信は小さなパケットで頻繁に発生します。

現在、私はAkkaのアクターを使用して、Scalaケースクラスをネットワーク経由でサーバーに素朴に送受信しています。次に例を示します。

sealed trait PlayerMessage
case class PlayerMove(dir: Vector3, run: Boolean) extends PlayerMessage
// more case classes...

次に、クライアントで:

server ! PlayerMove(dir, run)

サーバー上:

def receive = {
  case pm: PlayerMessage => pm match {
    case p @ PlayerMove(dir, run) =>
      // Move the player
      world.playerMove(dir,run)

      // More case tests..
    }

    // Send back entity states (this in fact occurs elsewhere, asynchronously)
    world.entities.foreach(ent => client ! ent.state()))

  // More message testing ...
  case _ => // ignore
}

ent.stateがEntityStateを返す場合:

case class BulletState(pos: Vector3, quat: Vector4, lin: Vector3, ang: Vector3)

sealed trait EntityState
case class EntityStatePlayer(id: Int, bullet: BulletState) extends EntityState
// more case classes...

これはすべてかなりうまく機能していますが、ご覧のとおり、他のケースクラスを含むケースクラスがたくさんあり、クライアントとサーバーの両方で一連のケーステストがあります。

  • シリアル化、逆シリアル化、およびマッチングによるパケットサイズとオーバーヘッドの両方を削減するにはどうすればよいですか?
  • ケースクラスの代わりにProtobufを使用すると、アプリケーションのパケットから脂肪が削減されますか?
  • このネットワークプロトコルの改善のために間違った場所を見ていますか?
4

1 に答える 1

7

Akkaは、デフォルトでJavaシリアル化またはGoogle Protobufsを使用します(ここここを参照)。アプリケーションに合わせてより最適化されたものをコーディングできると思われる場合は、独自のシリアライザーを定義できます。

ネットワークプロトコルを最適化したい場合は、お気に入りのネットワークスニファを調べて、実際に送受信されているものを見つける必要があります。そうすれば、何をすべきかをより適切に決定できます。

ただし、一般的には、より最適化されたネットワークプロトコルを手作業で作成できる可能性がありますが、変更が必要な場合は、脆弱で壊れやすくなります(ネットワークプロトコルの作成に多くの経験がある場合を除く)。

于 2012-03-19T19:03:25.073 に答える