2012-03-19 31 views
9

有点上下文优先:我正在用Scala编写客户端/服务器游戏(第一人称射击游戏),客户端需要向服务器发送移动意图每秒几十次,服务器也实时发回实体状态。在客户端(用于图形流动性)和服务器端都使用JBullet对这些实体进行物理模拟。每当客户端收到来自服务器的更新时,它就会用服务器发送的地址替换它的本地状态。当然,在同一时刻,同一台服务器上可能会有很多客户端。简而言之,在这个应用程序中,通信经常发生,只有小包。斯卡拉案例类与协议在网络上使用Akka的缓冲区

目前,我正在使用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而不是案例类删除我的应用程序的数据包中的脂肪?
  • 我在寻找改进这个网络协议的错误地方吗?

回答

7

阿卡使用Java序列化或谷歌Protobufs默认(参见herehere)。你可以定义你自己的序列化器,如果你认为你可以编写更适合你的应用程序的东西。

如果你想优化你的网络协议,你必须打破your favorite network sniffer找出实际上来回发送。然后你可以更好地决定做什么。但是,通常情况下,您可以手动创建更好的优化网络协议,但当您需要进行更改时,它很可能会变得脆弱并且中断(除非您有很多编写网络协议的经验) 。

+0

我已经阅读过这些内容,但是我还不清楚案例类是否被序列化为Google Protobuf;我猜不是。因此,我想知道如果完全值得,可以将我的案例类转换为Protobufs。他们周围的开销可能会消除任何真正的好处; Wireshark可以为以后提供帮助。 – gsimard 2012-03-19 19:27:18

+0

如果你的配置中有'proto =“akka.serialization.ProtobufSerializer”',Protobuf用于序列化。 – leedm777 2012-03-19 20:03:13

+4

阅读文档的相关部分:http://doc.akka.io/docs/akka/2.0/scala/serialization.html – 2012-03-19 21:04:34