这是一篇介绍协议类的文章。 用C编码的时候老师给我们讲socket通讯,将通讯流程确定为几个阶段:初始化包、打包、发包、收包、解包、处理包。其中所谓的包就是一个结构体,包含了需要传输的字段。 具体来讲,首先将结构体成员初始化完毕赋予相应的数值或者字串,其次将这个结构体各成员拼组到一个buffer中,发送方使用某种网络协议、比如socket发到接收方,接收方接收到数据之后将buffer中的字段依次解析到相应的结构体中,最后对这个结构体的数据进行处理。 用C编码的时候牵扯到几个基本接口: 1. Init()初始化结构体,有时候还需要为结构体成员申请空间。 2. Pack()将结构体成员依次拼装到buffer中,对于字串数据需要拼装字串长度和字串内容,对于整型数据需要变换字节序。如果在Init中申请过空间需要将其释放 3. Send()发送方调用某种网络协议接口发送数据,osp中可以调用osppost或者post发送 4. Recv()接收方调用某种网络协议接口接收数据,osp中InstanceEntry接收消息。 5. Unpack()接收方根据消息类型将buffer中的数据解析到相应的结构体中,或许又要申请空间,尤其当这个结构体中包含聊天信息等不定长字串时 6. Deal()接收方接收到消息对消息进行处理,osp中对不同的消息进行不同的处理。 程序员偷偷懒简化结构体结构,结构体字串成员直接使用数组,pack直接将结构体memcpy到buffer中或者直接发送结构体,大小为sizeof(structure),unpack直接将接收到的数据memcpy到结构体中。很明显这样并不规范。可是用那么规范的流程来处理这些数据又显得过于累赘、繁琐、耗费精力。而且要对每个协议结构进行重复的类似的操作。 原先工作编码,在协议结构处理这方面没有看到多大的需求,所以简化这个处理流程的想法也就没有付诸实施。最近在做demo时,简化流程出现了需求,在qq中涉及到多个协议结构,对每个协议结构进行类似的打包解包操作,实在耗费时间,所以我写了CPackage类来简化操作。 CPakcage类支持一系列的操作, 1. 包括管理一个buffer并且根据用户添加的字段自动更新buffer大小,在处理buffer时处理了内存碎片的问题,其实很简单,buffer的扩张分级增长即可; 2. 对用户经常使用的基本数据类型提供简化接口,比如WriteU8,ReadU8,WriteU64,ReadU64,在对这些基本数据类型提供支持的同时也支持分网络字节序和本地字节序存储两种方式; 3. 提供两种基本字串结构的支持,WriteShortString,ReadShortString,WriteString,ReadString,这两种字串结构存储结构式|u16|u8*|和|u32|u8*|; 4. 提供write、read等基本接口供用户自行操作buffer以及GetBuf等获取buffer等接口 5. 提供了pack和unpack两个纯虚函数供派生类实现打包和解包操作 CxxPackage就是具体的协议类,它继承自CPackage,提供结构成员,提供pack和unpack的实现,提供两个构造函数实现,一个构造函数用于打包(调用pack),一个构造函数用于解包(调用unpack)。用户可以添加其他函数以支持特定功能。具体实现后边代码介绍。 协议类的结构图:
打包和解包的代码是不是简化了很多呢。 我刚刚更新完CPakcage类的时同事正在使用Google Protocol Buffer,我也去体验了一把,粗浅的看,protocol buffer使用工具对协议结构加壳,提供给用户现成的操作接口,序列化和反序列化简便了不少,只是源码还需要阅读一段时间,对于协议结构字段的拼装方式一时还不确定,而且对于并不大的项目,我选择使用更简单的方法。还有tinyxml,这是一个不错的工具,虽然效率比不上protocol buffer,但是它也提供了丰富的key=value的构造和解析方法。同事积极使用流行的工具值得学习。CPakcage类的想法是简化协议包的构造和解析步骤,它没有提供那么多的功能,没有提供一种协议规范,应用范围在项目中网络传输模块的打包和解包步骤。CPackage效率还是很不错的,它具有微型身板儿。 保存、传输、交换数据,它能满足日常项目需求,在此把这个工具分享给同事,可以自由分发修改和保存,注明发源地哦。 (田端瑞) |