问题:如何在代码层面封装协议细节?如何将接收缓冲区中的数据解析成Message?深入思考数据是否可以解析成Message?如果数据量足够,是否可以解析多个Message?如果数据量不足以达到协议最小长度(12字节),如何处理剩余数据(属于下一个Message)?如何处理数据量超过最小长度但不足以创建Message的情况?初步解决方案定义了一个模块,用于从字节流中解析消息。它可以从指定的内存或指定的文件描述符中读取和解析。当至少有12个字节时,开始解析。首先解析协议中的头信息和数据区长度。(length)根据数据区的长度继续从字节流中读取数据(payload)当协议数据解析完成后,创建一个Message并返回,否则返回NULL协议解析模块parser的初步设计接口定义typedefvoidMParser;MParser*MParser_New();Message*MParser_ReadMem(MParser*parser,unsignedchar*mem,unsignedintlength);Message*MParser_ReadFd(MParser*parser,intfd);voidMParser_Reset(MParser*parser);voidMParser_Del(MParser*parser);解析器数据结构typedefstructmsg_parser{消息缓存;//缓存解析后的消息头intheader;//判断消息头是否解析成功intneed;//标识还剩多少字节来完成解析Message*msg;//解析中的协议消息(半成品)}MsgParser;条件:内存长度至少为12个连续字节memcpy(&p->cache,mem,p->need);p->cache.type=ntohs(p->cache.type);//从网络字节顺序转换为本地字节顺序p->cache.cmd=ntohs(p->cache.cmd);p->cache.index=ntohs(p->cache.index);p->cache.total=ntohs(p->cache.total);p->cache.length=ntohs(p->cache.length);mem+=p->need;length-=p->need;p->header=1;p->need=p->cache.length;从内存数据中读取payload(可以多次读取)if(!p->msg){//成功创建消息头后,创建一个Messagep->msg=malloc(sizeof(p->cache)+p->需要);如果(p->msg){*p->msg=p->cache;}}if(p->msg){unsignedintlen=(p->needp->need:length;unsignedintoffset=p->msg->length-p->need;memcpy(p->msg->payload+offset,mem,len);p->need-=len;}编程实验:协议分析模块的初步设计解析器,unsignedchar*mem,unsignedintlength);Message*MParser_ReadFd(MParser*parser,intfd);voidMParser_Reset(MParser*parse);voidMParser_Del(MParser*parse);#endifmsg_parser.c#include#include#include#include#include"msg_parser.h"typedefstructmsg_parser{消息缓存;整数头;内在需要;消息*msg;}MsgParser;MParser*MParser_New(){MsgParser*ret=calloc(1,sizeof(MsgParser));MParser_Reset(ret);returnret;}Message*MParser_ReadMem(MParser*parser,unsignedchar*mem,unsignedintlength){Message*ret=NULL;MsgParser*p=(MsgParser*)解析器;如果(!p||!mem||!length){返回ret;}if(!p->header){if(p->need<=length){memcpy(&p->cache,mem,p->need);p->cache.type=ntohs(p->cache.type);p->cache.cmd=ntohs(p->cache.cmd);p->cache.index=ntohs(p->cache.index);p->cache.total=ntohs(p->cache.total);p->cache.length=ntohl(p->cache.length);mem+=p->需要;长度-=p->需要;p->标题=1;p->need=p->cache.length;ret=MParser_ReadMem(解析器,内存,长度);}}else{if(!p->msg){p->msg=malloc(sizeof(p->cache)+p->need);如果(p->msg){*p->msg=p->cache;}}if(p->msg){unsignedintlen=(p->need需要:长度;unsignedintoffset=p->msg->length-p->need;memcpy(p->msg->payload,mem,len);p->需要-=len;}if(!p->need){ret=p->msg;p->msg=NULL;MParser_Reset(p);}}returnret;}Message*MParser_ReadFd(MParser*parser,intfd){Message*ret=NULL;返回ret;}voidMParser_Reset(MParser*parse){MsgParser*p=(MsgParser*)解析;如果(p){p->header=0;p->need=sizeof(p->缓存);免费(p->味精);p->msg=NULL;}}voidMParser_Del(MParser*parse){MsgParser*p=(MsgParser*)parse;如果(p){免费(p->味精);免费(p);}}test.c#include#include#include#include"msg_parser.h"intmain(){MParser*p=MParser_New();charbuf[]={0x00,0x01,0x00,0x02,0x00,0x03,0x00,0x04,0x00,0x00,0x00,0x04};字符数据[]={0x11,0x12,0x13,0x14};消息*m=MParser_ReadMem(p,buf,sizeof(buf));诠释我=0;if(!m){printf("再次解析...\n");m=MParser_ReadMem(p,数据,sizeof(数据));}printf("m=%p\n",m);如果(m){printf("type=%d\n",m->type);printf("cmd=%d\n",m->cmd);printf("索引=%d\n",m->索引);printf("总计=%d\n",m->总计);printf("长度=%d\n",m->length);for(i=0;ilength;++i){printf("0x%02x",m->payload[i]);}printf("\n");免费(米);}MParser_Del(p);返回0;:如何通过socket文件描述符实时分析协议数据?