|
本帖最后由 serverdev2012 于 2013-7-30 17:55 编辑
前段时间一直说要写一个分布式的内存nosql,本周开始准备动手写业务了,发现通信消息的构造与解析是个不小的工作量,所谓工欲善其事,必先利其器,于是写了这个通信协议,为什么不直接用protobuf,有2点主要原因
1.依赖第三方库,给用户安装部署上造成不方便
2.protobuf对每一个报文要定义个报文说明文件,然后生成一个类,也就是说,系统中将充斥着大量的报文类,这不是我希望看到的,虽然OOP就是如此,但我不希望如此极端。
我希望就一个类,解决所有报文,于是写了这个二进制的数据结构通信协议,该协议同样具备xml的结构化特性,基本可以看作一个二进制的xml,本着共建共享的精神,于是也在github上开源出来,一方面希望为大家带来便利,同时希望有空的朋友一起来完成java php python等语言的版本
协议介绍
二进制结构通信协议将结构以二进制方式保存到byte流中当前支持语言:C++,希望有空的朋友一起来完成java php python等语言的版本,想参与的朋友联系我QQ:49038554
在C++中对应的类为BStruct
协议格式:流长度(1.21版开始没有此数据)+ 成员1+...+成员n(成员之间没有分隔符)
成员也是一个二进制流格式:成员名长度(unsigned short字节序同上)+成员名(字符串不包含没有\0)+值长度(unsignedshort)+值(可以是一个嵌套的BStruct或BArray)
数组编码格式:元素大小(unsigned short,0表示元素大小变长)+元素1+...+元素n
元素编码格式:
如果元素大小非0(定长元素),就是一个值
如果元素大小为0(变长元素),值长度(unsigned short) + 值
(1.30版本开始已经突破此限制)一个BStruct最大拥有256个成员,不够用时,可嵌套BStruct扩展
成员名长度限制:1~256byte
数据类型:
short int long int32 int64等各整型数的字节顺序:高位在前,底位在后
不建议跨语言使用float double struct(c/c++专用),因为保存方式为memcpy方式复制进byte流,字节序为机器/系统api默认,其它语言不一定可以正确解析
协议样例(绿色为说明)
2D00 结构长度 :45byte msgid(11)+Student(34) 1.21版开始没有此数据
0500 msgid 成员名:成员名长度5byte,成员名: msgid
0200 D107 msgid值:值长度2byte,值2001
0700 Student 成员名:成员名长度7byte,成员名:Student
1700 值长度:23byte,值:一个BStruct(2结构长度 +21结构内容 )
Student的值是一个嵌套的BStruct结构
1500 结构长度:21byte name(13)+aga(8) 1.21版开始没有此数据
0400 name 成员名:成员名长度4byte,成员名:name
0500 huoyu name值:值长度5,值huoyu
0300 age 成员名:成员名长度3byte,成员名:age
0100 1F age值:值长度1,值31岁
使用范例:
BStruct结构转换进buf
char buf[256];
bsp::BStruct msg;
msg.Bind(buf,256);//绑定buf,添加数据都会复制入buf末尾
msg["msgid"] = (unsigned short)2001;//添加成员消息id,unsigned short类型
bsp::BStruct Student;//创建成员学生
/*
将Student与msg的缓冲末尾绑定(连接)
写入Student的数据,会直接写入msg末尾(即buf末尾)
*/
Student.Bind(msg.PreBuffer("Student"), msg.PreSize() );
Student["name"] = "huoyu";
Student["age"] = (char)31;
msg["Student"] = Student;//添加成员Student
msg.GetStream();//得到buf地址
msg.GetSize();//得到数据长度
从buf转回BStruct结构
char buf[256];//BStruct流
short size;//数据长度
//解析BStruct
bsp::BStruct msg;
if ( !msg.Resolve(buf,size) ) return;//解析
if ( !msg["msgid"].IsValid() ) return;//检查msgid是否存在,因为是范例,以下数据不再检查
unsigned short msgid = msg["msgid"];//取得msgid
bsp::BStruct Student = msg["Student"];//取得Student
string name = Student["name"];//取得name
char age = Student["age"];//取得age
相关连接
github下项目地址:https://github.com/huoyu820125/bstruct
googlecode下载地址:http://code.google.com/p/bstruct/
目前版本 V1.23
更新历史
V1.32(2013.07.30)
支持android的ndk
V1.31(2013.01.16)
1.对Null字符串,0长度字段增加支持2.增加IsEmpty接口用于判断,字段存在,但是值为NULL
V1.30(2012.12.19)
增加BArray,二进制数组编码
对数组进行支持
BStruct可与BArray互相嵌套
BStruct成员个数突破256限制(前一个无版本号的版本中更新的内容)
V1.23(2012.12.18)
更新时候忘记了前一版本是1.21,直接将版本号跳到了1.23
扩大BStruct兼容的大小,从unsigned short扩大大unsigned int
相应的修正相关方法与成员类型
V1.21(2012.12.18)
将编码头部的2byte总长度从编码中删除,向json xml一样,不带头部信息
由用户在不同场合自己定义头部
相应的解码时,获取BStruct大小的方式就不再是short len = memtoi( buf, 2 )了,
按照用户自己定义的头部解析了。
V1.20(2012.12.14)
主要加强了对非法数据流的适应能力
1.删除所有assert
2.可以得到赋值/取值成功/失败结果
取值检查:msg[""].IsVaild()
赋值检查:if ( !(msg[""] = 值) )
3.BStruct增加IsVaild()方法检查一个BStruct对象是否有效,主要用于解析嵌套的BStruct
msg["key"].IsVaild()可能是有效的数据,但msg["key"]如果不是一个BStruct,那么BStruct sub = msg["key"];sub可能就是无效的(无法解析msg["key"]指向的二进制流)
V1.0(2012.12.12)
发布,支持C++语言
|
|