« 绕过 c api 直接访问 lua 表 | 返回首页 | Lua 调试器 »

sproto 的一些更新

sproto 是我设计的一个类 google protocol buffers 的东西。

在很多年前,我在我经手的一些项目中使用 google protocol buffers 。用了好几年,经历了几个项目后,我感觉到它其实是为静态编译型语言设计的协议,其实并没有脱离语言的普适性。在动态语言中,大家都不太愿意使用它(json 更为流行)。一个很大的原因是,protobuffers 是基于代码生成工作的,如果你不使用代码生成,那么它自身的 bootstrap 就非常难实现。

因为它的协议本身是用自身描述的,如果你要解析协议,必须先有解析自己的能力。这是个先有鸡还是先有蛋的矛盾。过去很多动态语言的 binding 都逃不掉引入负责的 C++ 库再加上一部分动态代码生成。我对这点很不爽,后来重头实现了 pbc 这个库。虽然它还有一些问题,并且我不再想维护它,这个库加上 lua 的 binding 依然是 lua 中使用 protobuffer 的首选。

protobuffer 自身有很长的历史,历史带来了包袱,实际上在我放弃 protobuffer 后不久,google 也大刀阔斧的更新了 3.0 版,对之前 2.x 版做了很多必要的,不兼容的改进。

我仿照 protobuffer 的基本理念设计了 sproto ,设计上的考虑在之前的 blog 中已经写了很多。

sproto 的设计理念之一:保证基本能用的基础上足够简单,不增加太多特性。如果要增加新特性,都是仔细考虑过,并保持不破坏兼容性。最近一段时间,我给 sproto 加了两个特性,这里简单介绍一下:

其一,sproto 没有内置的浮点数类型。因为我觉得大多数项目中,传输浮点数的必要性都不大。如果必须传输的话,可以用字符串,或二进制串来替代。由传输的双方来共同约定保证一致性。

但是,有时候传输小数的需求依然存在。我认为定点数可以是一种选择,而且不必破坏原有的协议,也不必增加新的类型。只需要在 sproto 的协议描述中加一些备注。

之前给 sproto 加字典支持就是靠备注实现的

这次我选择在 integer 类型后面加一个备注,比如写 integer(2) 就表示,这个整数类型是一个有两位十进制小数位的定点数。两端在解析同样的协议时,需要在编码的时候 * 100 取整再编码,解码的时候 /100 还原。

如果有一端使用老版本的实现,那么可以在跟上层自行乘除 100 来兼容。

第二,sproto 用 string 类型来传输字符串和二进制串。它可以自然对应到 lua 中的 string 类型。但是,很多其它语言中,可阅读的 string 和 binary 串是两种不同的类型。其 string 类型需要额外指定编码。

sproto 缺乏 binary 串的描述,会在 python c# 等语言中遇到一些麻烦。

考虑之后,我决定给 sproto 增加 binary 类型,但为了兼容,把它作为 string 的一个子类型实现。在新版的 sproto 中,你可以在协议文件中定义 binary 字段。但编码时,还是按 string 编码的,不会破坏兼容性。

但新版本的代码在解码的时候,会根据协议定义,正确的通知 binding 层,这是一个 binary 串。

Comments

使用dynamic_message即可。完全不用生成代码。lua里很方便

以前一直用protobuf, 后来发现生成协议代码比较麻烦,所以选择了json, 现在有了spoto, 感觉更加方便了。既有json的特性,又有了强类型的支持。但是紫熏实现的C#版sproto仍然需要生成C#代码。如果能像lua这样用key-value查询就好了。

PDL是异构编程的协议.

接手的一个项目, 服务器端java, 客户端C++. 通讯协议一开始用的JSON, 因为没有静态类型的支持, 这东西得纯靠记忆, 一旦修改协议, 要是忘记了在另一端相应调整代码, 就很痛苦. 一开始的想法是统一两端的语言, 协议部分共用代码. 后来发现了protocol buffers, 正好解决了问题

Post a comment

非这个主题相关的留言请到:留言本