求一个关于 protobuffer 项目的解决方案

2014-11-20 16:27:13 +08:00
 YORYOR
求解答:
我们现在有这样一个问题,client 和server 都依赖同一批proto文件,client用java实现,server用c++实现,现在想把这写proto文件以及proto文件生成的代码作成一个公共的项目,让client和server来依赖这个项目,那么问题来了,java可以通过pom搞定,c++那边怎么整,有解决方法吗,,多谢
3491 次点击
所在节点    程序员
14 条回复
c4pt0r
2014-11-20 16:42:17 +08:00
没懂,用 pom 干嘛, git submodule 不就行了吗
damngood
2014-11-20 16:57:29 +08:00
现在做的项目客户端 C#, 服务端 Golang 共用一个 proto 文件.
我在服务端写了个脚本, 一旦发现有变化自动运行 protoc

c++ 不也应该差不多的么. 一旦有变化 regenerate, 然后 rebuild.
yuankui
2014-11-20 17:24:11 +08:00
你把生成的文件弄进vcs,那不是恶心人吗?
YORYOR
2014-11-20 18:29:20 +08:00
@c4pt0r 正在尝试。

@yuankui 生成要使用的java文件哪恶心到人了
benjiam
2014-11-20 18:57:03 +08:00
proto的传输格式是什么样子的?转成string 再加个长度 type然后传吗
goofansu
2014-11-20 19:34:40 +08:00
@YORYOR 生成的文件一般是不进版本控制的,应该是测试的时候build出来
rrfeng
2014-11-20 19:52:30 +08:00
同意楼上。vcs 里只放 proto 文件就好了。项目 build 的时候生成各自的程序。
yueyoum
2014-11-21 10:28:30 +08:00
我的用法是 一个单独的 git repo, 放 protobuf 定义

然后 server 和 client 的 仓库 都去添加那个 protobuf 的仓库为 submodule

当 protobuf修改 提交后 , server 和 client 都 git submodule update 一下,
最后各自生产各自的代码就行
yueyoum
2014-11-21 10:28:58 +08:00
@damngood 一看就是做手游的吧, unity3d, golang server ?
damngood
2014-11-21 11:08:48 +08:00
@yueyoum 恩, 是的
yueyoum
2014-11-21 11:36:35 +08:00
刚好我今早还想到 要自己做一个轮子,
因为 protobuffer 岁好,但是 在erlang中使用起来确实麻烦,
如果自己定义 消息的二进制结构,那么每个消息服务端和客户端都要自己去 pack/unpack,
比protobuf这种麻烦多了,

于是便有了这个想法:
用python写protocol定义, 然后生成对应语言的操作代码
生成的代码直接去 pack/unpack 二进制数据。

这样 protocol 定义写起来非常方便,而且自动生成各种语言的代码,
方便,省事,而且为了简单轻量:

可能有以下特性:

1. 不做错误检查, pack进去的数据由 人保证不写错, 否则在 serialize 的可能会报错
2. 生成的代码,没有压缩算法,一个 32位整数,哪怕你之填充了一个1, 那么也是老老实实的占用4个字节。
3. 保持简单,生成的二进制结构就是这么的stupid:

Binary:
[4 bytes length][ * body *]
Body:
[4 bytes protocol id][ * data *]
Data:
[1 byte date type sign number][ * value * ]...
[1 byte date type sign number][4 bytes string length][* string value *]...
[1 byte date type sign number][4 bytes repeated amount][* repeated value *]...
Repated Value:
[1 byte date type sign number][* value *]...




比如举个例子:
协议定义

class Weapon(EmbeddedProtocol):
----id = IntegerField(bytes=4)
----attack = FloatField()

@Spec(protocol_id=10) # 协议号
class Person(Protocol):
----id = IntegerField(bytes=8) # 64 bits integer
----gender = IntegerField(bytes=1) # 8 bits integer
----name = StringField()
----position = PointField()
----weapons = ListField(Weapon)


然后用python直接生产对应语言的 代码。
python例子(以及所有支持OOP的语言),生成后的代码使用起来类似这样:

p = Person()
p.id = 1
p.gender = 1
p.name = "My Name"
p.position = (23, 56)
p.weapons.extend([
----Weapon(id=11, attack=99),
----Weapon(id=12, attack=101),
])

binary = p.Serialize()


erlang 例子,生成后的代码使用类似这样:

P = person:new(),
P1 = person:set(P, id, 1),
P2 = person:set(P1, gender, 1),
%% 或者一次设置多个Field
P3 = P2#person(name=<<"My Name">>, position=[23, 56]),

W1 = weapon:new(#weapon(id=11, attack=99)),
W2 = weapon:new(#weapon(id=12, attack=101)),


P4 = person:append_to_field(P3, weapons, [W1, W2])

Binary = person:serialize(P4)
yueyoum
2014-11-21 11:37:31 +08:00
@damngood 我也是做手游的, 交流一下

我QQ 330912736
damngood
2014-11-21 21:58:20 +08:00
@yueyoum 多谢抬爱.
不过我很少上 qq 聊天. 一般最多上下手机 qq. 真有事情才上桌面 qq. 没啥就是觉得 Mac qq 太耗 cpu 了...
YORYOR
2014-11-28 18:46:49 +08:00
@yueyoum 感谢 之前一直是想把生成的代码也丢进去,后来发现多余了 submmodule里面只放pb文件就行!

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/148034

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX