美文网首页
iOS项目中使用protobuf

iOS项目中使用protobuf

作者: 一只努力的猿 | 来源:发表于2017-12-05 18:22 被阅读0次

          上一篇讲了protobuf环境的配置(iOS 使用protobuf(一)环境的配置),这一篇将会讲到protobuf在项目中的实际的使用。

          因为protobuf最后会被编译成字节流,通过socket发送个服务端,所以就牵涉到以下几个问题:

               1)将数据发送到服务端的时候,服务端怎么样去将接收到的数据从数据包中解析出来的问题?

               2)怎么样去判断接收到的数据是完整的?

               3)怎么样截取完整的数据,并且映射成对象?

               4)怎么样同时发起多个请求

    一:通信我们现在的做法是依赖socket来发送和接收

               使用socket就会牵扯到粘包的问题:

                    1)为了判断是否该包数据是否是完整的一包数据,我们的包头是包体内容经过base128编码后的长度的值,来作为包头。

    -(NSMutableData *)dataWithRawVarint32:(int64_t)value//进行128编码

    {

        NSMutableData *valData = [[NSMutableData alloc] init];

        while (true) {

            if ((value & ~0x7F) == 0) {//如果最高位是0,只要一个字节表示

                    [valData appendBytes:&value length:1];

                    break;

               } else {

                    int valChar = (value & 0x7F) | 0x80;//先写入低7位,最高位置1

                    [valData appendBytes:&valChar length:1];

                    value = value >> 7;//再写高7位

               }

            }

            return valData;

        }

                    2)服务器收到数据之后就会先切出包头的数据,获取到包体的数据,判读一下长度是否是一样的。如果不一样那么这包数据就是作废的。直接告诉客户端是失败的,如果是完整的数据,处理完,返回正确的数据给客户端

    二:解析返回来的数据,判断完整性

            1)将返回来的数据进行base128反编码,获取到包体的长度,用这个包长度截取出包体的数据

                int length =(int)[self getProtoBUfLenght:data];

                newData= [data subdataWithRange:NSMakeRange(data.length-length, length)];

                -(NSInteger)getProtoBUfLenght:(NSData *)data//反编码 获取到真是的数据体的长度 {

                         int32_t lenth=0;

                        GPBCodedInputStream * input = [[GPBCodedInputStream alloc] initWithData:data];

                        enth = (int32_t)[input readInt64];

                        return lenth;

                }

            2)然后去判断length和包头中的数据长度是否一致

    三:依赖(二)中获取到的newData,将newData进行protobuf编码,映射成对象。然后我们就能直接像使用oc对象一样去使用这个对象

            QPack * pack = [QPack parseFromData:newData error:nil];

    进行第三步的时候有可能会解析失败,原因有可能是服务端返回来的数据格式不是标准的protobuf数据格式,所有就会解析失败,这时候只需要将data直接转换为字符串,打印比较一下就好

    四:同时发起多个请求

           为什么要说这个,那是因为有可能网络因素和服务端响应等影响,有可能就会出现数据混乱的问题。

    比如说:我在a页面发起了a的请求,过了一会没有响应。现在来到b页面发起了b请求,但是现在返回来的数据确实a请求的数据。这样就会发生数据错乱的问题。怎么解决呢?

    当然解决的办法很多,我的做法是,在protobuffer中增加一个messageid(使用当前的时间经过base128编码生成来的)的字段。每次都是用这个字段去判断返回来的消息,就不会出现错乱的问题,也可以同时进行多请求。

    相关文章

      网友评论

          本文标题: iOS项目中使用protobuf

          本文链接:https://www.haomeiwen.com/subject/qysdxxtx.html