可用的游戏网络协议定义语言和代码生成

11

我一直在寻找一个好的通用二进制网络协议定义框架,以提供一种编写多语言实时游戏服务器和客户端的方式(例如Java后端服务器和使用Objective-C和Cocoa编写的iPhone前端客户端)。

我想支持Java Flash客户端、iPhone客户端和Windows上的C#客户端(以及XNA客户端上的XBOX)。

我正在寻找一种有效地通过TCP/IP或UDP套接字流连接发送/接收消息的方法。我不希望使用可以通过HTTP Web Service发送的东西,如JSON或XML封送的对象。虽然Hessian的二进制Web服务协议是一个非常有趣的解决方案。

我想要一个网络协议格式和客户端/服务器基本实现,允许客户端连接到服务器并发送任何在定义协议中的消息,并接收协议中的任何消息,而无需绑定到某种RPC端点。我想要一个通用的流来处理协议中的任何消息,这样我就可以支持像服务器每100毫秒向所有客户端发送游戏中各个实体的位置等功能。


这个语句的意思是什么:“无需绑定到某种RPC端点”? - grieve
“不必绑定到某种RPC端点”意味着在服务器端,我不希望它仅能接受RPC请求,而是希望它能够启动对客户端的反向请求,并接收消息。基本上,我不想要一个RPC客户端/服务器设置,我想要一个客户端消息流和服务器消息流,其中消息在某个IDL中定义,该IDL可以为多种语言的客户端/服务器生成代码绑定。 - Dougnukem
我现在明白你的意思了。谢谢你的澄清。 - grieve
前段时间,我在SO上问了一个与此相关的问题,你可能想查看一下以获取更多指针:<a href="https://dev59.com/r0bRa4cB1Zd3GeqP4eCK">实验协议设计/开发工具?</a> - none
9个回答

15

我找到的网络协议框架如下:

  1. Google's Protocol Buffer - 但是它缺乏对于从给定协议发送/接收任意消息的支持。
  2. Apache Thrift - 一个有趣的选择,但它主要针对RPC,而不是通用游戏客户端/服务器套接字类型的连接,其中客户端或服务器可以随时发送消息,而不仅仅是响应客户端RPC请求。
  3. Raknet Multiplayer - Raknet 提供了完整的多人游戏网络库(对于收入低于 $250k 的独立开发者来说是免费的)。

更新 :OculusVR 收购了 RakNet 并且现在是免费/开源的。您可以在 Github 上找到它。

  1. Hessian Binary Web Service Protocol - 是一个 HTTP Web 服务二进制协议,非常适合发送二进制数据,无需使用附件扩展协议。

Raknet 提供了一个很好的面向游戏/仿真的多人游戏库。

Apache Thrift 和 Google 的 Protocol Buffers 似乎是在游戏网络协议客户端/服务器架构中使用的最简单方法。

Hessian 如果你想创建一个基于 Web 的游戏服务器,使用 Java 或 Flash 客户端以及一些类型的服务器推送技术(如 COMET )。Hessian 可能提供了一种非常有趣的方式来支持 Web 上的实时游戏,甚至能够在 VM Web 解决方案(如 Google App Engine 或 Amazon EC2)上托管它们。

有关在游戏和其他用途中使用各种协议定义框架的讨论:


2
个人而言,我会首先看一下 Protocol Buffers,因为现在似乎有支持多种语言的支持。您不需要使用 RPC 来发送 ProtoBufs,因此只要首先指定长度(例如长度|protobuf|长度|protobuf...),就可以轻松地通过套接字流式传输它们。唯一的缺点是所有消息都必须预先定义,这可能是一件好事。 - mattkemp

2
This text is already in Chinese. If you meant to provide a different text for me to translate, please let me know.

1

如果您真的关心多平台和语言问题,请务必考虑endian问题。为此设计的二进制协议必须使用网络字节序,因此需要自定义每种数据类型的序列化函数;您不能仅仅将C结构体盲目地推入网络缓冲区。

游戏公司解决这个问题的常见方法是使用协议描述语言或规范,以简单格式(如XML、Python或Lua)编写,并为每个目标语言生成代码,生成带有数据结构和序列化的数据包类。该规范可以使用从基本类型开始扩展到包括具有语义信息、枚举或更复杂结构的游戏特定类型的类型系统。例如,数据文件可能如下所示:

Attack = {
  source = 'objectId',
  target = 'objectId',
  weapon = 'weapon::WEAP_MAIN',
  seed = 'int'
}

这可能会生成类似以下的代码:

#define PT_ATTACK 10002

class PacketAttack : public Packet {
  public:
    PacketAttack () : m_packetType(PacketAttack::s_packetType) {}

    ObjectId m_source;
    ObjectId m_target;
    WeaponType m_weapon;
    int m_seed;

   bool Write(Stream* outStream) {
       Packet::Write(outStream);
       outStream << m_source;
       outStream << m_target;
       outStream << m_weapon
       outStream << m_seed;
   }

   bool Read(Stream* inStream);

 static const int s_packetType;
};

这确实需要更多的基础设施... 流、数据包基类、安全序列化函数等。


1

如果您选择编写自己的协议,您可能想阅读我在这里发布的答案。

简而言之,它讨论了编写协议时应考虑的内容,并列出了一些版本控制和保持向前和向后兼容性的技巧。


0
因为您想要使用不同的编程语言,同时也想要一些简洁/小巧的东西,我建议使用谷歌的协议缓冲。您需要一个预先编译的RPC部分,但我真的认为这是当您开始混合不同语言时的最佳选择。以下是链接:http://code.google.com/apis/protocolbuffers/docs/overview.html

0
为什么不直接实现UDP?你的问题大多数都提到了你不想要什么... 除了UDP之外,你还想要什么形式的抽象层面?
下载Quake III源代码,看看他们如何在UDP上构建游戏更新?
IP协议的设计是为了以统一的方式支持多个设备/操作系统,这不是你所要求的吗? 哪种协议在广泛的系统范围内都有实现呢?嗯,也许是IP协议?

我所讨论的协议并不完全是UDP或TCP实现的低级传输协议。我谈论的是应用层协议。根据我对Quake III网络模型(http://www.tilion.org.uk/Games/Quake_3/Network_Protocol)的了解,他们实现了一个非常简单的游戏命令子集以发送给每个客户端。接收这些消息的网络代码是用C编写的客户端/服务器,我正在寻找一种自动化代码生成的方法,以便我可以使用相同的应用程序协议在其他语言(如Java/Objective-c)中创建客户端/服务器。 - Dougnukem

0

我想重申Bill K的建议。自己编写协议并不难。

对于iPhone端,可以看一下AsyncSocket,它支持基于分隔符的TCP数据包,并且很容易构建一个使用数据包头的解决方案。

如果你想快速拥有一个测试服务器来与iPhone上的AsyncSocket进行对战,可以看一下Naga(用于Java服务器部分),它已经准备好了基于分隔符的数据包和带有数据包头的数据包。Naga在部分编写时考虑了网络游戏。


0

我不同意“使用简单分隔字符串方法”的做法:问题是,到底有什么好处?写更多的代码并维护它们? 我唯一能想到的原因是缺乏工具支持(为某些奇怪的平台编写),或者特定的(非常)高性能或消息大小限制。 或者,有时候,真的想要编写一个格式——这是可以的,但必须有明确的理由。

根据确切的需求,我建议考虑JSON,因为它可以读取和写入任意消息;对于Java有很好的对象绑定器(就像xml一样),比二进制格式更容易阅读,并且在许多用例中都足够好。

如果消息大小非常重要,Protobuf可以很好地工作——虽然它的大小并不总是像gzip替代方案(gzip+xml,gzip+json压缩得非常好)那样小,但通常很接近。


@StaxMan,我完全同意编写自定义协议是浪费时间的,而且在支持多种语言或进行扩展时会导致维护困难。JSON和gzip+json可能是一个不错的选择,特别适用于编写Web服务,但我更关注的是在不需要或不想使用文本格式(比如Web服务)的情况下,当你构建一个游戏服务器(像《魔兽世界》或《雷神之锤III》)时,你会希望使用快速的二进制消息协议,这种情况下将JSON解析为本地对象/结构可能会限制性。 - Dougnukem

0

ASN.1符合“良好的通用二进制网络协议定义框架”的定义。它还被ITU-T标准化,因此有很多现有的工具和库可用于各种语言。

DER编码适用于高效的网络通信,XER编码适用于人类可读(和可写)的永久存储。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接