zoukankan      html  css  js  c++  java
  • 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都会保留。反序列化成功。

  • 相关阅读:
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    并行导致的进程数过大无法连接数据库
    Oracle 等待事件(Wait Event):Sync ASM rebalance 解析
    2套RAC环境修改scanip后客户端连接异常
    数据流通技术工具
    Hack The Box——Scavenger
    MySQL中InnoDB引擎对索引的扩展
    30分钟,教你从0到1搞定一次完整的数据可视化分析!
    【2020-MOOC-浙江大学-陈越、何钦铭-数据结构】树和堆(第五周的笔记和编程作业)
  • 原文地址:https://www.cnblogs.com/lixiao24/p/10097836.html
Copyright © 2011-2022 走看看