iOS项目中使用protobuf

2017-12-05  本文已影响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编码生成来的)的字段。每次都是用这个字段去判断返回来的消息,就不会出现错乱的问题,也可以同时进行多请求。

上一篇下一篇

猜你喜欢

热点阅读