基于 Google protobuf 的 webgame 网络协议设计

Post on 03-Sep-2014

9.233 views 12 download

Tags:

description

 

Transcript of 基于 Google protobuf 的 webgame 网络协议设计

基于 基于 Google protobuf Google protobuf 的 的 wwebgame ebgame 网络协议设计网络协议设计赖勇浩

http://laiyonghao.com2010.8.28

Google Protopuf 2.3• http://code.google.com/p/protobuf/• 二进制协议描述语言• C++• Java• Python• other languages

人生苦短,我用 人生苦短,我用 PythonPython 。。

基本流程• Define message formats in a .proto

file.• Use the protocol buffer compiler.• Use the Python protocol buffer API to

write and read messages.

Quick Example• message Person {• required int32 id = 1;• required string name = 2;• optional string email = 3;• }

Use the protocol buffer compiler.

• protoc -I=$SRC_DIR --python_out=$DST_DIR $SRC_DIR/example.proto

• class Person(message.Message):• __metaclass__ =

reflection.GeneratedProtocolMessageType• DESCRIPTOR = _PERSON

Python protocol buffer API• person = Person()• person.id = 10• person.name = 'lai'• person.email = 'mail@laiyonghao.com'• with open('person.data', 'wb') as f:• print >>f, person.SerializeToString()

Exception• person.no_such_field = 1 # raises

AttributeError• person.id = "1234" # raises

TypeError

• with open('example.data', 'rb') as f:• data = f.read()• person = Person()• person.ParseFromString(data)• assert person.id == 10• assert person.name == 'lai'• if person.hasField('email'):• assert person.email == 'mail@laiy...'

ActionScript 3.0• http://code.google.com/p/protoc-gen-as3/• It has most protobuf 2.3 features, more than any other protobuf's as3 implementation.• And you can use (as3_bindable) option to generate classes with Bindable metadata tag.• 国人开发(网易杭研杨博)• http://hi.baidu.com/atry/

How to use it?• protoc --plugin=protoc-gen-

as3=path/to/protoc-gen-as3[.bat] --as3_out=output-path your.proto

目标• as3

– var sock:SdSocket = new SdSocket(...);– var p:Person = new Person();– ...– sock.send(p);

• python– sock = SdSocket(...)– ...– person = sock.recv()– print person.id, person.name

问题• 客户端 / 服务器端怎么知道对方发过来的包是 Person ?

好问题!• 需要设计一个 header• message Header {• required uint32 length = 1;• required uint32 msg_id = 2;• }

我在代码里没有看到 msg_id !• Person 的 msg_id 是什么?• msg_id <=> hash(Person.DESCRIPTOR.full_name)• 需要一个极佳的 hash 函数(完全无冲突)• 额外的好处:防外挂(一点额外的操作)

消息分发是一件操蛋的事!消息分发是一件操蛋的事!

• svr = TcpServer(Handler(Protocol('full_name_map_msg_id.xml')))• svr.run_forever()

更进一步• class Handler extends Object {

– public function _handle_Person(p:Person):void {• trace(p.id.toString());• trace(p.name);• if(p.hasEmail()){

– trace(p.email);• }

– }• }

• class Handler(object):– def _handle_Person(self, person):

• print person.id, person.name• if(person.hasField('email')):print person.email

开始像 开始像 RPC RPC 了?了?对的,这是我们更高的目标。

Thanks all !Thanks all !Q&A

别提性能问题。