通过网络使用Akka的Scala案例类与协议缓冲区

gsi*_*ard 9 scala protocol-buffers case-class actor akka

首先介绍一下上下文:我在Scala(第一人称射击游戏)中编写客户端/服务器游戏,其中客户端需要每秒向服务器发送几十次运动意图并且服务器将实体状态发送回来,实时也是如此.在客户端(用于图形流动性)和服务器端使用JBullet对这些实体进行物理模拟.每当客户端从服务器接收更新时,它都会将其本地状态替换为服务器发送的状态.当然,在给定时刻,同一服务器上可能有许多客户端.简而言之,在这种应用中,通信经常发生,带有小数据包.

目前,我正在使用Akka的演员天真地通过网络将Scala案例类发送到服务器并返回.这是一个例子:

sealed trait PlayerMessage
case class PlayerMove(dir: Vector3, run: Boolean) extends PlayerMessage
// more case classes...
Run Code Online (Sandbox Code Playgroud)

然后在客户端:

server ! PlayerMove(dir, run)
Run Code Online (Sandbox Code Playgroud)

在服务器上:

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
}
Run Code Online (Sandbox Code Playgroud)

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...
Run Code Online (Sandbox Code Playgroud)

这一切都运行良好,但正如您所看到的,有很多案例类,有时包含其他案例类,以及客户端和服务器上的一堆案例测试.

  • 如何从序列化,反序列化和匹配中减少数据包大小和开销?
  • 使用Protobuf代替案例类会减少应用程序数据包的负担吗?
  • 我是否在寻找改进此网络协议的错误位置?

lee*_*777 7

Akka默认使用Java序列化或Google Protobufs(参见此处此处).如果您认为可以编写针对您的应用程序更优化的内容,则可以定义自己的序列化程序.

如果你想优化网络协议,你必须打破你最喜欢的网络嗅探器,找出实际上来回发送的内容.然后你可以更好地决定做什么.

但是,一般情况下,您可以手动创建一个更好的优化网络协议,但是当您需要进行更改时,它更容易变脆(除非您有很多编写网络协议的经验).

  • 阅读文档的相关部分:http://doc.akka.io/docs/akka/2.0/scala/serialization.html (4认同)
  • @gsimard,嗨,你有没有想过如何确保案例类已经在protobuf中序列化了?proto ="akka.serialization.ProtobufSerializer"足够吗?我想我们还需要做出其他改变吗? (2认同)