加入收藏 | 设为首页 | 会员中心 | 我要投稿 应用网_丽江站长网 (http://www.0888zz.com/)- 科技、建站、数据工具、云上网络、机器学习!
当前位置: 首页 > 站长资讯 > 外闻 > 正文

教你从头写游戏服务器框架

发布时间:2019-02-23 14:24:51 所属栏目:外闻 来源:腾讯游戏学院
导读:副标题#e# 1.需求 由于越通用的代码,就是越没用的代码,所以在设计之初,我就认为应该使用分层的模式来构建整个系统。按照游戏服务器的一般需求划分,最基本的可以分为两层: 底层基础功能:包括通信、持久化等非常通用的部分,关注的是性能、易用性、扩展

Request 和 Response 两个类,都有记录序列号的 seq_id 字段,但 Notice 没有。Protocol 类就是负责把一段 buffer 字节数组,转换成 Message 的子类对象。所以需要针对三种 Message 的子类型都实现对应的 Encode() / Decode() 方法。

  1. class Protocol { 
  2.  
  3. public: 
  4.     virtual ~Protocol() { 
  5.     } 
  6.  
  7.     /** 
  8.      * @brief 把请求消息编码成二进制数据 
  9.      * 编码,把msg编码到buf里面,返回写入了多长的数据,如果超过了 len,则返回-1表示错误。 
  10.      * 如果返回 0 ,表示不需要编码,框架会直接从 msg 的缓冲区读取数据发送。 
  11.      * @param buf 目标数据缓冲区 
  12.      * @param offset 目标偏移量 
  13.      * @param len 目标数据长度 
  14.      * @param msg 输入消息对象 
  15.      * @return 编码完成所用的字节数,如果 < 0 表示出错 
  16.      */ 
  17.     virtual int Encode(char* buf, int offset, int len, const Request& msg) = 0; 
  18.  
  19.     /** 
  20.      * 编码,把msg编码到buf里面,返回写入了多长的数据,如果超过了 len,则返回-1表示错误。 
  21.      * 如果返回 0 ,表示不需要编码,框架会直接从 msg 的缓冲区读取数据发送。 
  22.      * @param buf 目标数据缓冲区 
  23.      * @param offset 目标偏移量 
  24.      * @param len 目标数据长度 
  25.      * @param msg 输入消息对象 
  26.      * @return 编码完成所用的字节数,如果 < 0 表示出错 
  27.      */ 
  28.     virtual int Encode(char* buf, int offset, int len, const Response& msg) = 0; 
  29.  
  30.     /** 
  31.      * 编码,把msg编码到buf里面,返回写入了多长的数据,如果超过了 len,则返回-1表示错误。 
  32.      * 如果返回 0 ,表示不需要编码,框架会直接从 msg 的缓冲区读取数据发送。 
  33.      * @param buf 目标数据缓冲区 
  34.      * @param offset 目标偏移量 
  35.      * @param len 目标数据长度 
  36.      * @param msg 输入消息对象 
  37.      * @return 编码完成所用的字节数,如果 < 0 表示出错 
  38.      */ 
  39.     virtual int Encode(char* buf, int offset, int len, const Notice& msg) = 0; 
  40.  
  41.     /** 
  42.      * 开始编码,会返回即将解码出来的消息类型,以便使用者构造合适的对象。 
  43.      * 实际操作是在进行“分包”操作。 
  44.      * @param buf 输入缓冲区 
  45.      * @param offset 输入偏移量 
  46.      * @param len 缓冲区长度 
  47.      * @param msg_type 输出参数,表示下一个消息的类型,只在返回值 > 0 的情况下有效,否则都是 TypeError 
  48.      * @return 如果返回0表示分包未完成,需要继续分包。如果返回-1表示协议包头解析出错。其他返回值表示这个消息包占用的长度。 
  49.      */ 
  50.     virtual int DecodeBegin(const char* buf, int offset, int len, 
  51.                             MessageType* msg_type) = 0; 
  52.  
  53.     /** 
  54.      * 解码,把之前DecodeBegin()的buf数据解码成具体消息对象。 
  55.      * @param request 输出参数,解码对象会写入此指针 
  56.      * @return 返回0表示成功,-1表示失败。 
  57.      */ 
  58.     virtual int Decode(Request* request) = 0; 
  59.  
  60.     /** 
  61.      * 解码,把之前DecodeBegin()的buf数据解码成具体消息对象。 
  62.      * @param request 输出参数,解码对象会写入此指针 
  63.      * @return 返回0表示成功,-1表示失败。 
  64.      */ 
  65.     virtual int Decode(Response* response) = 0; 
  66.  
  67.     /** 
  68.      * 解码,把之前DecodeBegin()的buf数据解码成具体消息对象。 
  69.      * @param request 输出参数,解码对象会写入此指针 
  70.      * @return 返回0表示成功,-1表示失败。 
  71.      */ 
  72.     virtual int Decode(Notice* notice) = 0;protected: 
  73.  
  74.     Protocol() { 
  75.     } 
  76.  
  77. }; 

这里有一点需要注意,由于 C++ 没有内存垃圾搜集和反射的能力,在解释数据的时候,并不能一步就把一个 char[] 转换成某个子类对象,而必须分成两步处理。

先通过 DecodeBegin() 来返回,将要解码的数据是属于哪个子类型的。同时完成分包的工作,通过返回值来告知调用者,是否已经完整的收到一个包。

调用对应类型为参数的 Decode() 来具体把数据写入对应的输出变量。

(编辑:应用网_丽江站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读