protobuf使用

Google Protocol Buffer(简称 Protobuf)是一种轻便高效的结构化数据存储格式,平台无关、语言无关、可扩展,可用于通讯协议数据存储等领域。

用于socket的数据传输在合适不过了。

编译很麻烦,所以谷歌提供了插件:https://github.com/google/protobuf-gradle-plugin

项目源码地址:https://github.com/google/protobuf

下面例子是在socket中的只用,解决了 tcp的粘包和分包问题:

/**
 * 发送封装消息
 *
 * @return
 * @throws IOException
 */
public byte[] getByte1() throws IOException {
    MsgProtos.Msg msg = MsgProtos.Msg.newBuilder().setText("hello").build();
    //在包体前 加入一个包长度字段
    byte[] body = msg.toByteArray();
    int bodyLen = body.length;
    //java int 4个字节
    //protobuf 如果来编码这个int 数据 需要占用多少个字节
    //最大占用 5个 字节
    int headLen = CodedOutputStream.computeUInt32SizeNoTag(bodyLen);
    Log.e(TAG, "包头需要占用:" + headLen + "字节");
    byte[] head = new byte[headLen];
    //将 protobuf 编译的 bodyLen 写入到 head 里面
    CodedOutputStream cos = CodedOutputStream.newInstance(head);
    cos.writeUInt32NoTag(bodyLen);
    cos.flush();

    //head 表示包长度
    // 包总长度 包头+包体长度
    byte[] data = new byte[headLen + bodyLen];
    System.arraycopy(head, 0, data, 0, headLen);
    System.arraycopy(body, 0, data, headLen, bodyLen);
    return data;
}
/**
 * 接收解析
 *
 * @param cache
 * @throws IOException
 */
static void processCache(ByteBuf cache) throws IOException {
    // 包头最大5个字节
    byte[] buf = new byte[5];
    for (int i = 0; i < buf.length; ++i) {
        // 如果cache中 不可以读取数据了
        if (!cache.isReadable()) {
            cache.resetReadIndex();
            return;
        }
        //1-5个字节都有可能
        // 读取一个字节
        buf[i] = cache.get();
        //解码出长度
        int length = CodedInputStream.newInstance(buf, 0, i + 1).readRawVarint32();
        //可能就是包头=包体长度
        if (length > 0) {
            //尝试去解析 protobuf 包体
            //如果可读数据小于 包长度
            if (cache.readableBytes() < length) {
                cache.resetReadIndex();
                return;
            }
            //读取length 个 字节数据
            byte[] b = cache.get(length);
            //处理完的数据 丢掉 不然cache会越来越大
            cache.discardRead();
            //反序列化
            MsgProtos.Msg msg = MsgProtos.Msg.parseFrom(b);
            System.out.println(msg.getText());
        }

    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值