C++ protobuffer 前后端通信 简单应用

后端发送多个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里面还有'',所以,如果把char*直接赋值给string,会被丢弃。所以上面代码中memcpy ,assign都会保留。反序列化成功。

原文地址:https://www.cnblogs.com/lixiao24/p/10097836.html