在C / C ++多人游戏中,对网络消息进行序列化和反序列化的最佳方法是什么?


11

我们现在正在使用JSON,并希望将客户端和服务器之间的某些类型的消息转换为二进制格式。

我应该将结构读入套接字吗?使用质子缓冲液/旧货吗?

我应该如何表示数据数组?

用于打包/拆包数据的界面应该是什么样?

Answers:


12

假设...

  1. 您正在谈论转换为字节缓冲区
  2. 您正在使用UDP,因此性能值得关注

尽量避免浪费数据包中的空间来定义结构。IE至少发送一个字节来表示数据包的类型,然后假设接收到的每个数据包都遵循该数据包类型的预定义结构

我应该将结构读入套接字吗?使用质子缓冲液/旧货吗?

  • 是的,如果您需要整个结构,请阅读整个结构
  • 不,自己制作数据包结构,这肯定比使用这些方法进行序列化要小;您应该确切知道数据包应包含哪些数据

我应该如何表示数据数组?

  • 作为数据数组。接收时继续读取缓冲区,直到数据结束,以避免发送数组元素的Count

用于打包/拆包数据的界面应该是什么样?

  • 您可以轻松地设置一堆将基本类型转换为字节的方法,然后在这些方法的基础上再构建自定义类型。有关如何执行此操作的详细信息几乎可以在我确定的任何地方找到(我个人使用C#)

最后一点,包大小一个问题,特别是对于快照而言:大小= packetSize x实体x connectedPlayers; 因此,每个数据包可能有60 x 10 x 16 = 9,600字节,然后每秒发送20次:= 192,000 bps = 187 KBps。这显然是具有较高上传速度的乐队。因此,需要在可能的情况下最小化影响分组大小的每个因素。

这篇文章极大地帮助了我: Valve多人网络


另一篇文章,我在阅读各种对象序列化和网络在这里发现的问题在几个星期前是这一个,它描述了虚幻引擎是怎么做的。阀源的一个很好的比较点。
Martin Foot

1
在一般情况下,您的数组方法不起作用-“数据结尾”在哪里?即使您的消息是定界的,这也意味着每个结构最多只能有1个数组。要解决此问题,原始发布者可以坚持使用固定长度的数组,或者确保每个结构只有一个数组(在结构的末尾),或者在数组的开头发送计数值。
Kylotan

还有一个提示:记住要治疗神经病,如果您不知道这种事情存在,这可能会很烦人。

好点@Kylotan,同意在某些情况下无法避免这些额外的数据;但是,如果我发现自己将多个数组添加到单个数据包中,我会考虑改为发送多个数据包
确实是2011年

1

此问题已由Google和Facebook解决:

  1. Google的协议缓冲区-Google是C ++的大用户:

    协议缓冲区是一种以有效但可扩展的格式对结构化数据进行编码的方法。Google几乎所有内部​​RPC协议和文件格式都使用协议缓冲区。

  2. Apache Thrift(以前为Facebook):

    Thrift是用于可扩展的跨语言服务开发的软件框架。它结合了软件堆栈和代码生成引擎,以构建可在C ++,Java,Python,PHP,Ruby,Erlang,Perl,Haskell,C#,Cocoa,JavaScript,Node.js,Smalltalk和OCaml之间高效且无缝运行的服务。


Google的协议缓冲区对于大型实时游戏而言太慢了。但是,由于版本控制,我确实发现它们非常适合原型制作和较小的播放器数量。和往常一样,您的探查器将讲述真实的故事。
Patrick Hughes

好吧,它们对于Google来说已经足够好了,Google的伸缩性也很好,而且当我使用它们时,它们也能很好地工作。这就是为什么我推荐他们。
带薪的书呆子

Google不需要实时性能。Google确实需要可靠性和正常运行时间,而协议缓冲区可以很好地满足这两个要求。所有后备版本控制和样板代码生成的复杂性都会增加开销,当您以50-100msec的间隔发送和接收1000个更新时,它的总和就会增加。针对特定于手头数据的编码串行器,对一个协议缓冲区的多个旧版本进行概要分析。@ indeed005具有要点。
Patrick Hughes

+1,因为尽管这些格式对于大多数实时或高带宽游戏而言有点太大且速度太慢(由于包含了允许您重构任意复杂数据包的额外信息),但这并不是说它们并没有用一些游戏,例如 回合制 如果不需要优化每个资源,那么这些格式可以为您节省很多时间,并且肯定比JSON更有效。
Kylotan
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.