基于 google protobuf 的 webgame 网络协议设计
DESCRIPTION
TRANSCRIPT
基于 基于 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 = '[email protected]'• 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
别提性能问题。