后端发送多个protobuffer消息到前端,前端用socket监听,如何区分消息类型呢?
//定义心跳包
DseHeartbeat _DseHeartbeat;
DseHeartbeat _DseHeartbeat1;
_DseHeartbeat.set_time( 1544432682 ); char a[1000]; memset ( a ,0,1000); std::string str; _DseHeartbeat.SerializeToString( &str ); memcpy(a,str.c_str(),str.length()); _DseHeartbeat1.ParseFromString(str);
定义了一个proto,设置int字段为当前的时间戳,可以看到被反序列化成了以上内容。
可以在string的前面添加两个字段,1个是4位的消息长度,另一个是4位的消息类型。
1 enum S2C_EVENT 2 { 3 C2S_DceLimitTank = 4215 , //DceLimitTank 4 S2C_DseUserData = 770 , //DseUserData 5 S2C_DseLimitTank = 669, 6 S2C_DseActivityData = 516 , 7 S2C_DseHeartbeat = 660 , 8 };
定义几个消息的类型。
客户端在解析的时候:
int iostring_readInt ( const char* d ,int offset ) { int ret = 0; d += offset; ret = (*d & 0xff) << 24; d++; ret += (*d & 0xff) << 16; d++; ret += (*d & 0xff) << 8; d++; ret += *d & 0xff; return ret; }
void handleData ( int size ) { int index = 0; while (index<size) { int headlen = sizeof ( unsigned short )+ sizeof ( unsigned int ); int len = iostring_readInt ( buf+ index ); int pkgType = iostring_readInt ( buf + index ,sizeof ( unsigned int ) ); int requireLen = len - sizeof ( unsigned int ); if (requireLen> 0 ) { char* response = new char[requireLen]; memcpy ( response ,buf+index + 8 ,requireLen ); std::string str2; str2.assign ( response ,requireLen ); switch (pkgType) { case S2C_DseHeartbeat: qDebug () << _DseHeartbeat.ParseFromString ( str2 ); qDebug ( ("心跳包" + std::to_string ( _DseHeartbeat.time () )).c_str () ); break; case S2C_DseActivityData: qDebug () << _DseActivityData.ParseFromString ( str2 ); qDebug ( ("活动:oil " + std::to_string ( _DseActivityData.oiltime () )).c_str () ); break; case S2C_DseUserData: qDebug () << _DseUserData.ParseFromString ( str2 ); qDebug ( ("玩家名" + _DseUserData.name () +" level:" +std::to_string ( _DseUserData.level () )).c_str () ); break; case S2C_DseLimitTank: _DseLimitTank.ParseFromString ( str2 ); _DropList = _DseLimitTank.maindrop (); for (const DropData& _DropData1 : _DropList.droplist ()) { qDebug () << (("droplist: type:" + std::to_string ( _DropData1.type () ) + " id:" + std::to_string ( _DropData1.id () ))).c_str (); } qDebug () << QString ( "错误码 %1" ).arg ( _DseLimitTank.res () ); default: break; } } index = index+len+4; } }
因为客户端在recv的时候,可能一次读取多条消息,所以每次读取前四位(该消息的长度)->下四位(消息类型)->消息的内容->把消息ParseFromString 反序列化。
在这里反序列化失败过几次,因为protobuf里面还有'\0',所以,如果把char*直接赋值给string,\0会被丢弃。所以上面代码中memcpy ,assign都会保留\0。反序列化成功。