Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

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

  • Login to see the comments

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

  1. 1. 基于 Google protobuf 的 webgame 网络协议设计 赖勇浩 http://laiyonghao.com 2010.8.28
  2. 2. Google Protopuf 2.3 <ul><li>http://code.google.com/p/protobuf/ </li></ul><ul><li>二进制协议描述语言 </li></ul><ul><li>C++ </li></ul><ul><li>Java </li></ul><ul><li>Python </li></ul><ul><li>other languages </li></ul>
  3. 3. 人生苦短,我用 Python 。
  4. 4. 基本流程 <ul><li>Define message formats in a .proto file. </li></ul><ul><li>Use the protocol buffer compiler. </li></ul><ul><li>Use the Python protocol buffer API to write and read messages. </li></ul>
  5. 5. Quick Example <ul><li>message Person { </li></ul><ul><li>required int32 id = 1; </li></ul><ul><li>required string name = 2; </li></ul><ul><li>optional string email = 3; </li></ul><ul><li>} </li></ul>
  6. 6. Use the protocol buffer compiler. <ul><li>protoc -I=$SRC_DIR --python_out=$DST_DIR $SRC_DIR/example.proto </li></ul>
  7. 7. <ul><li>class Person(message.Message): </li></ul><ul><li>__metaclass__ = reflection.GeneratedProtocolMessageType </li></ul><ul><li>DESCRIPTOR = _PERSON </li></ul>
  8. 8. Python protocol buffer API <ul><li>person = Person() </li></ul><ul><li>person.id = 10 </li></ul><ul><li>person.name = 'lai' </li></ul><ul><li>person.email = 'mail@laiyonghao.com' </li></ul><ul><li>with open('person.data', 'wb') as f: </li></ul><ul><li>print >>f, person.SerializeToString() </li></ul>
  9. 9. Exception <ul><li>person.no_such_field = 1 # raises AttributeError </li></ul><ul><li>person.id = &quot;1234&quot; # raises TypeError </li></ul>
  10. 10. <ul><li>with open('example.data', 'rb') as f: </li></ul><ul><li>data = f.read() </li></ul><ul><li>person = Person() </li></ul><ul><li>person.ParseFromString(data) </li></ul><ul><li>assert person.id == 10 </li></ul><ul><li>assert person.name == 'lai' </li></ul><ul><li>if person.hasField('email'): </li></ul><ul><li>assert person.email == 'mail@laiy...' </li></ul>
  11. 11. ActionScript 3.0 <ul><li>http://code.google.com/p/protoc-gen-as3/ </li></ul><ul><li>It has most protobuf 2.3 features, more than any other protobuf's as3 implementation. </li></ul><ul><li>And you can use (as3_bindable) option to generate classes with Bindable metadata tag. </li></ul><ul><li>国人开发(网易杭研杨博) </li></ul><ul><li>http://hi.baidu.com/atry/ </li></ul>
  12. 12. How to use it? <ul><li>protoc --plugin=protoc-gen-as3=path/to/protoc-gen-as3[.bat] --as3_out=output-path your.proto </li></ul>
  13. 13. 目标 <ul><li>as3 </li></ul><ul><ul><li>var sock:SdSocket = new SdSocket(...); </li></ul></ul><ul><ul><li>var p:Person = new Person(); </li></ul></ul><ul><ul><li>... </li></ul></ul><ul><ul><li>sock.send(p); </li></ul></ul><ul><li>python </li></ul><ul><ul><li>sock = SdSocket(...) </li></ul></ul><ul><ul><li>... </li></ul></ul><ul><ul><li>person = sock.recv() </li></ul></ul><ul><ul><li>print person.id, person.name </li></ul></ul>
  14. 14. 问题 <ul><li>客户端 / 服务器端怎么知道对方发过来的包是 Person ? </li></ul>
  15. 15. 好问题! <ul><li>需要设计一个 header </li></ul><ul><li>message Header { </li></ul><ul><li>required uint32 length = 1; </li></ul><ul><li>required uint32 msg_id = 2; </li></ul><ul><li>} </li></ul>
  16. 16. 我在代码里没有看到 msg_id ! <ul><li>Person 的 msg_id 是什么? </li></ul><ul><li>msg_id <=> hash(Person.DESCRIPTOR.full_name) </li></ul><ul><li>需要一个极佳的 hash 函数(完全无冲突) </li></ul><ul><li>额外的好处:防外挂(一点额外的操作) </li></ul>
  17. 17. 消息分发是一件操蛋的事!
  18. 18. <ul><li>svr = TcpServer(Handler(Protocol('full_name_map_msg_id.xml'))) </li></ul><ul><li>svr.run_forever() </li></ul>
  19. 19. 更进一步 <ul><li>class Handler extends Object { </li></ul><ul><ul><li>public function _handle_Person(p:Person):void { </li></ul></ul><ul><ul><ul><li>trace(p.id.toString()); </li></ul></ul></ul><ul><ul><ul><li>trace(p.name); </li></ul></ul></ul><ul><ul><ul><li>if(p.hasEmail()){ </li></ul></ul></ul><ul><ul><ul><ul><li>trace(p.email); </li></ul></ul></ul></ul><ul><ul><ul><li>} </li></ul></ul></ul><ul><ul><li>} </li></ul></ul><ul><li>} </li></ul>
  20. 20. <ul><li>class Handler(object): </li></ul><ul><ul><li>def _handle_Person(self, person): </li></ul></ul><ul><ul><ul><li>print person.id, person.name </li></ul></ul></ul><ul><ul><ul><li>if(person.hasField('email')):print person.email </li></ul></ul></ul>
  21. 21. 开始像 RPC 了? 对的,这是我们更高的目标。
  22. 22. Thanks all ! Q&A 别提性能问题。

×