您好,欢迎访问三七文档
当前位置:首页 > 临时分类 > protobuf消息定义原则
录[-]1.使用protobuf的enum定于消息的编号,也就是消息的类型。2.会为每个具有消息体的消息定义一个对应的protobufmessage。例如Login_Request会有一个对应LoginRequest消息。3.会为每个消息大类定义一个消息,例如命令消息全部包含在messageCommand中,请求消息全部包含在Request消息中,应答消息全部包含在Response消息中,指示消息全部包含在Indication消息中。4.对于应答消息,并非总是成功的,因此在应答消息中还会包含另外2个字段。一个用于描述应答是否成功,一个用于描述失败时的字符串信息。对于有多个应答的消息来说,可能会包含是否为最后一个应答消息的标识。应答的序号(类似与网络数据包被分包以后,协议要合并时,需要知道分片在包中的具体位置)。因此Response看起来想这样:5.最后我会定义一个大消息,把Command、Request、Response、Indication全部封装在一起,让后在通信的时候都动大消息开始编解码。大消息看起来想下面这样。。6.发送数据和接收数据。6.消息处理(C++)7.wireshark抓包1网络通信涉及到消息的定义,不管是使用二进制模式、xml、json等格式。消息都可以大体的分为命令消息、请求消息、应答消息和指示消息4大消息类型。一般情况下每个消息还还有包含一个序列号和一个能够唯一区分类型类型的消息编号,编号可以使用字符串、整数或者枚举等。1.使用protobuf的enum定于消息的编号,也就是消息的类型。我会为每个系统都定义一个MSG枚举。包含系统用到的所有消息的枚举编号01enumMSG02{03Login_Request=0x00001001;04Login_Response=0x00001002;0506XXX_Request=0x00001003;07XXX_Request=0x00001004;0809XXX_Command=0x00002001;1011XXX_Indication=0x00003001;12}2.会为每个具有消息体的消息定义一个对应的protobufmessage。例如Login_Request会有一个对应LoginRequest消息。1messageLoginRequest2{3requiredbytesusername=1;4requiredstringpassword=2;5}3.会为每个消息大类定义一个消息,例如命令消息全部包含在messageCommand中,请求消息全部包含在Request消息中,应答消息全部包含在Response消息中,指示消息全部包含在Indication消息中。也就是我会有下面4个protobufmessage:01messageCommand02{//包含所有的XXXCommand消息03}04messageRequest05{//包含所有的XXXRequest消息06}07messageResponse08{//包含所有的Response消息09}10messageIndication11{//包含所有的Indication消息。12}4.对于应答消息,并非总是成功的,因此在应答消息中还会包含另外2个字段。一个用于描述应答是否成功,一个用于描述失败时的字符串信息。对于有多个应答的消息来说,可能会包含是否为最后一个应答消息的标识。应答的序号(类似与网络数据包被分包以后,协议要合并时,需要知道分片在包中的具体位置)。因此Response看起来想这样:1messageResponse2{3requiredboolresult=1;4optionalbyteserror_description=2;5requiredboollast_block=3;6requiredfixed32block_index=4;7.....//其他的字段为XXXResponse..8}5.最后我会定义一个大消息,把Command、Request、Response、Indication全部封装在一起,让后在通信的时候都动大消息开始编解码。大消息看起来想下面这样。。01messageMessage02{03requiredMSGtype=1;04requiredfixed32sequence=2;0506optionalRequestrequest=3;07optionalResponseresponse=4;08optionalCommandcommand=5;09optionalIndicationindication=6;10}6.发送数据和接收数据。用于UDP的时候比较简单,因为每个数据包就是一个独立的Message消息,可以直接解码,或者编码后直接发送。但是如果是使用于TCP的时候,由于涉及到粘包、拆包等处理,而且Message消息里面也没有包含长度相关的字段(不好处理),因此把Message编码后的消息嵌入另外一个二进制消息中。使用4字节消息长度+Message(二进制数据)+(2字节CRC校验(可选))其中4字节的内容,只包含Message的长度,不包含自身和CRC的长度。如果需要也可以包含,当要记得通信双方必须一致。6.消息处理(C++)编解码后,根据Message.type字段,可以知道要处理的消息,进行分发。不过一般情况下我不喜欢if、switch。所以我比较倾向于使用虚函数来处理。因此一般情况下我会定义一下的处理方法。01#pragmaonce0203#includeMessage.pb.h04#includememory05#includemap0607#includeClient.h0809usingstd::shared_ptr;1011classBaseHandler12{13public:14BaseHandler(pbmsg::MSGtype):type_(type){15Register(this);16}17virtual~BaseHandler(){}1819pbmsg::MSGGetType()const{returntype_;}20//具体处理方法,由派生类实现.21virtualvoidProcess(constshared_ptrpbmsg::Message&msg,constshared_ptrClient&client)=0;2223//注册消息处理方法24staticvoidRegister(BaseHandler*);25//执行指定的消息,查询处理方法,调用Process。26staticvoidExecute(constshared_ptrpbmsg::Message&msg,constshared_ptrClient&client);27private:28pbmsg::MSGtype_;293031private:32staticstd::mappbmsg::MSG,BaseHandler*handers;33};34//每个消息都实现Process的一个特化版本...35templatepbmsg::MSGType36classMessageHandler:publicBaseHandler37{38public:39MessageHandler(void):BaseHandler(Type){}40~MessageHandler(void){}4142voidProcess(constshared_ptrpbmsg::Message&msg,constshared_ptrClient&client);43private:44staticMessageHandlerthisHandler;4546};474849///放在.cpp\.cxx文件中.5051voidBaseHandler::Register(BaseHandler*h)52{53handers[h-GetType()]=h;54}555657voidBaseHandler::Execute(constshared_ptrpbmsg::Message&msg,...其它参数)58{59autoit=handers.find(msg-type());60if(it!=handers.end())61{62it-second-Process(msg,client);63}else{64LOG(ERROR)消息msg-type()没有对应的处理方法.\n;;65}66}11//对每个MSG枚举的消息值,都会特化一个Process方法。1template2voidMessageHandlerpbmsg::Login_Request::Process(constshared_ptrpbmsg::Message&msg,...其它参数){}1//并且在全局空间创建对象,系统启动时,自动创建。如果需要在堆空间中分配,另行封装方法,并调用下面的代码,让编译器实例化类。01MessageHandlerpbmsg::Login_RequestMessageHandlerpbmsg::Login_Request::thisHandler;020304050607div08091011121314/div01p02//最后消息处理:非常的easy:03/p0405p06shared_ptrpbmsg::MessagerecvMessage(newpbmsg::Message());07boolparserOk=recvMessage-ParseFromArray((msg.rd_ptr()+4),msg.size()-4);08if(parserOk){0910BaseHandler::Execute(recvMessage,...其它参数);1112}13/p7.wireshark抓包protobuf是二进制的消息,wireshark抓包是无法直接分析的。不过google上面已经有了插件。不过插件只支持UDP.本人在google上面的protobuf-wireshark的基础上修改了支持TCP的抓包解析,前提是顶层Message只有一个,而且封装在4个字节的长度后面。插件下载地址(wireshark1.8.6版本).CSDN没分数的可以callme,留下你的邮箱。分布式应用中基于事件驱动的应用开发模型本文将为您讲述如何为分布式应用建立事件驱动的开发模型。并以Linux系统为例,展示了事件驱动开发的基本框架。1评论:郭洪锋(ghf_email@sohu.com),2001年8月01日内容前言从目前看,大量数据的流动仍然主要分布在局域网的分布式系统中,该类系统的大流量、实时性的特点要求系统具有实时响应、交互动作异步非耦合、高可用性、高可得到性等特征。而因为系统主要局限在局域网内运行,因而在系统的构建上应用要具有灵活多样可靠稳定的性能。事实上,良好的局域网应用是联入广域网的前提。在该类分布式系统中,引导数据流动和分布式动作的往往是事件的作用,或者称之为消息。事件是激活和驱动分布式系统的直接原因,也是进一步构建分布式对象管理的基础。利用事件驱动开发模型,可以快速构建分布式系统应用,提高分布式应用和整个分布式系统的运行效率。回页首事件驱动的开发模型首先,在分布式系统中,事件是异步非耦合的,这是系统实时性的要求。因为在分布式系统中,往往各个关键应用既是服务器应用,也是客户应用,相互之间从功能上看是对等关系,如果在同步情况下,一个应用驱动了另一个应用的事件,这个应用则必须堵塞,以等待事件执行的返回状态,这样这个应用在这段时间内则不能处理实时事件。而各个应用之间相互不完全依赖的情况也决定了分布式系统中事件的两端必须为非耦合。事件驱
本文标题:protobuf消息定义原则
链接地址:https://www.777doc.com/doc-2852947 .html