欢迎来到天天文库
浏览记录
ID:18569850
大小:101.50 KB
页数:9页
时间:2018-09-19
《thrift之tprotocol类体系原理及源码详细解析之紧凑协议类tcompactprotocolt(tcompactprotocol)》由会员上传分享,免费在线阅读,更多相关内容在教育资源-天天文库。
1、这个协议类采用了zigzag 编码,这种编码是基于Variable-length quantity编码提出来的,因为Variable-length quantity编码对于负数的编码都需要很长的字节数,而zigzag 编码对于绝对值小的数字,无论正负都可以采用较少的字节来表示,充分利用了 Varint技术。所以这个协议类采用zigzag 编码可以节省传输空间,使数据的传输效率更高。至于zigzag具体的编码实现方式可以网上查查,其实就是把从低位到最后一个还存在1(二进制)的最高位表示出来就可以了。这
2、个协议类对外提供的方法和上面介绍的二进制协议相同,这样可以很方便使用者从一种协议改变到另一种协议。下面我同样结合scribe提供的Log方法来分析这个协议类的功能,不过不会像上面二进制协议在把整个过程分析了,我只会分析与协议相关的部分了,分析一些比较难懂的一些函数功能,分析的思路还是按照函数调用过程来分析。首先还是分析writeMessageBegin函数,下面是这个函数的实现代码:1templateuint32_tTCompactProtocolT3、rt_>::writeMessageBegin(23conststd::string&name,constTMessageTypemessageType,constint32_tseqid){45uint32_twsize=0;67wsize+=writeByte(PROTOCOL_ID);//写入这个协议的产品ID号:为0x8289wsize+=writeByte((VERSION_N&VERSION_MASK)4、(((int32_t)messageType<5、&TYPE_MASK));//写入此协议的版本号和消息类型:前3位是消息类型,后面5位是协议版本号10http://yaya.qqq23.com11wsize+=writeVarint32(seqid);//写入请求序列号1213wsize+=writeString(name);//写入消息名称(也就是函数调用名称)1415returnwsize;//返回写入的大小,多少字节1617} 因为这些协议类都是模板类,所以每一个函数也就是模板函数了。函数具体的功能代码里有详细注释,其中的writeByte6、函数就是写入一个字节到服务器。这里与二进制协议不同的是这里写入请求序列号(也就是对于所有的整型数)都调用的writeVarint32函数,这个函数就是采用zigzag编码写入整型数到服务器,代码如下:1templateuint32_tTCompactProtocolT::writeVarint32(uint32_tn){23uint8_tbuf[5];//对于一个整数,zigzag编码最大采用5个字节保存45uint32_twsize=0;67、7while(true){89if((n&~0x7F)==0){//判断除了最低7位是否还有其他高位为1(二进制)1011buf[wsize++]=(int8_t)n;//没有了代表着就是最后一个字节1213break;//退出循环1415}else{1617buf[wsize++]=(int8_t)((n&0x7F)8、0x80);//取最低7位加上第8位(为1代表后续还有字节属于这个整数,为0代表这是这个整数的最后一个字节了。1819n>>=7;//移走已经编码的位数2021}2223}2425t9、rans_->write(buf,wsize);//写入编码的字节数26http://jiazu.qqq23.com27returnwsize;//返回写入的字节数2829} 这个函数的功能就是对整数进行Variable-length quantity编码后写入,如果为负数需要处理。如果不处理那么每一个负数都需要5个字节来编码,因为最高位表示符号位,而负数的符号位用1表示(也就是说负数的最高位永远为1)。处理的方式也很简单(就是zigzag编码),就是把最高位(符号位)移动到最低位,最低位到次高位一10、次向高位移动一位,代码如下(就一句就实现了):1template23uint32_tTCompactProtocolT::i32ToZigzag(constint32_tn){45return(n<<1)^(n>>31);67} 上面写入整数和处理负数都是针对的32位的,当然也有64位的相应函数,实现方式相同。我们在回到writeMessageBegin函数,里面还有一个writeString函数用来写入一个字
3、rt_>::writeMessageBegin(23conststd::string&name,constTMessageTypemessageType,constint32_tseqid){45uint32_twsize=0;67wsize+=writeByte(PROTOCOL_ID);//写入这个协议的产品ID号:为0x8289wsize+=writeByte((VERSION_N&VERSION_MASK)
4、(((int32_t)messageType<5、&TYPE_MASK));//写入此协议的版本号和消息类型:前3位是消息类型,后面5位是协议版本号10http://yaya.qqq23.com11wsize+=writeVarint32(seqid);//写入请求序列号1213wsize+=writeString(name);//写入消息名称(也就是函数调用名称)1415returnwsize;//返回写入的大小,多少字节1617} 因为这些协议类都是模板类,所以每一个函数也就是模板函数了。函数具体的功能代码里有详细注释,其中的writeByte6、函数就是写入一个字节到服务器。这里与二进制协议不同的是这里写入请求序列号(也就是对于所有的整型数)都调用的writeVarint32函数,这个函数就是采用zigzag编码写入整型数到服务器,代码如下:1templateuint32_tTCompactProtocolT::writeVarint32(uint32_tn){23uint8_tbuf[5];//对于一个整数,zigzag编码最大采用5个字节保存45uint32_twsize=0;67、7while(true){89if((n&~0x7F)==0){//判断除了最低7位是否还有其他高位为1(二进制)1011buf[wsize++]=(int8_t)n;//没有了代表着就是最后一个字节1213break;//退出循环1415}else{1617buf[wsize++]=(int8_t)((n&0x7F)8、0x80);//取最低7位加上第8位(为1代表后续还有字节属于这个整数,为0代表这是这个整数的最后一个字节了。1819n>>=7;//移走已经编码的位数2021}2223}2425t9、rans_->write(buf,wsize);//写入编码的字节数26http://jiazu.qqq23.com27returnwsize;//返回写入的字节数2829} 这个函数的功能就是对整数进行Variable-length quantity编码后写入,如果为负数需要处理。如果不处理那么每一个负数都需要5个字节来编码,因为最高位表示符号位,而负数的符号位用1表示(也就是说负数的最高位永远为1)。处理的方式也很简单(就是zigzag编码),就是把最高位(符号位)移动到最低位,最低位到次高位一10、次向高位移动一位,代码如下(就一句就实现了):1template23uint32_tTCompactProtocolT::i32ToZigzag(constint32_tn){45return(n<<1)^(n>>31);67} 上面写入整数和处理负数都是针对的32位的,当然也有64位的相应函数,实现方式相同。我们在回到writeMessageBegin函数,里面还有一个writeString函数用来写入一个字
5、&TYPE_MASK));//写入此协议的版本号和消息类型:前3位是消息类型,后面5位是协议版本号10http://yaya.qqq23.com11wsize+=writeVarint32(seqid);//写入请求序列号1213wsize+=writeString(name);//写入消息名称(也就是函数调用名称)1415returnwsize;//返回写入的大小,多少字节1617} 因为这些协议类都是模板类,所以每一个函数也就是模板函数了。函数具体的功能代码里有详细注释,其中的writeByte
6、函数就是写入一个字节到服务器。这里与二进制协议不同的是这里写入请求序列号(也就是对于所有的整型数)都调用的writeVarint32函数,这个函数就是采用zigzag编码写入整型数到服务器,代码如下:1templateuint32_tTCompactProtocolT::writeVarint32(uint32_tn){23uint8_tbuf[5];//对于一个整数,zigzag编码最大采用5个字节保存45uint32_twsize=0;6
7、7while(true){89if((n&~0x7F)==0){//判断除了最低7位是否还有其他高位为1(二进制)1011buf[wsize++]=(int8_t)n;//没有了代表着就是最后一个字节1213break;//退出循环1415}else{1617buf[wsize++]=(int8_t)((n&0x7F)
8、0x80);//取最低7位加上第8位(为1代表后续还有字节属于这个整数,为0代表这是这个整数的最后一个字节了。1819n>>=7;//移走已经编码的位数2021}2223}2425t
9、rans_->write(buf,wsize);//写入编码的字节数26http://jiazu.qqq23.com27returnwsize;//返回写入的字节数2829} 这个函数的功能就是对整数进行Variable-length quantity编码后写入,如果为负数需要处理。如果不处理那么每一个负数都需要5个字节来编码,因为最高位表示符号位,而负数的符号位用1表示(也就是说负数的最高位永远为1)。处理的方式也很简单(就是zigzag编码),就是把最高位(符号位)移动到最低位,最低位到次高位一
10、次向高位移动一位,代码如下(就一句就实现了):1template23uint32_tTCompactProtocolT::i32ToZigzag(constint32_tn){45return(n<<1)^(n>>31);67} 上面写入整数和处理负数都是针对的32位的,当然也有64位的相应函数,实现方式相同。我们在回到writeMessageBegin函数,里面还有一个writeString函数用来写入一个字
此文档下载收益归作者所有