首页 > 其他分享 >[原]Android上GTalk以及Push机制的XMPP数据选择使用protobuf格式而非XML格式

[原]Android上GTalk以及Push机制的XMPP数据选择使用protobuf格式而非XML格式

时间:2023-06-02 21:38:06浏览次数:29  
标签:XML protobuf public static ProtoBufType 格式 byte final


[url]http://code.google.com/p/protobuf/[/url]

[b]先介绍下什么是protobuf以及有什么好处.[/b]
[i]Protocol Buffers are a way of encoding structured data in an efficient yet extensible format. Google uses Protocol Buffers for almost all of its internal RPC protocols and file formats. [/i]

[b]protobuf在网络编程中的应用思考[/b]

protobuf是google提供的一个开源序列化框架,类似于XML,JSON这样的数据表示语言,其最大的特点是基于二进制,因此比传统的 XML表示高效短小得多。虽然是二进制数据格式,但并没有因此变得复杂,开发人员通过按照一定的语法定义结构化的消息格式,然后送给命令行工具,工具将自动生成相关的类,可以支持java、c++、python等语言环境。通过将这些类包含在项目中,可以很轻松的调用相关方法来完成业务消息的序列化与反序列化工作。

protobuf在google中是一个比较核心的基础库,作为分布式运算涉及到大量的不同业务消息的传递,如何高效简洁的表示、操作这些业务消息在google这样的大规模应用中是至关重要的。而protobuf这样的库正好是在效率、数据大小、易用性之间取得了很好的平衡.

[b]Android上GTalk以及Push机制的XMPP数据选择使用protobuf格式[/b]
Android上Google Talk客户端以及C2DM等Push机制基于XMPP协议, 而XMPP协议通信的数据格式是XML. 正如上面所介绍的, protobuf比XML高效, 节约流量. 所以, 在这里, Google选择将protobuf作为数据格式.
实现起来也不是很复杂. 对于传统的使用XML作为数据格式的XMPP协议, 发送Packets的时候将对象数据serialize为相应的XML格式的数据, 接收Packets的时候将XML格式的数据parse为对象数据; 而对于GTalk使用protobuf作为数据格式的XMPP协议, 发送Packets的时候将对象数据serialize为相应的protobuf格式的数据, 接收Packets的时候将protobuf格式的数据parse为对象数据.
[b]
1. 针对不同的XML Packet类型用不同的字节值表示.[/b]
GtalkCoreMessageTypes定义了不同的XML Packet类型

HEARTBEAT_PING
public static final ProtoBufType HEARTBEAT_ACK;
public static final ProtoBufType LOGIN_REQUEST;
public static final ProtoBufType LOGIN_RESPONSE;
public static final ProtoBufType CLOSE;
public static final ProtoBufType MESSAGE_STANZA;
public static final ProtoBufType PRESENCE_STANZA;
public static final ProtoBufType IQ_STANZA;
public static final ProtoBufType DATA_MESSAGE_STANZA;
public static final ProtoBufType BATCH_PRESENCE_STANZA;
public static final ProtoBufType STREAM_ERROR_STANZA;
public static final ProtoBufType HTTP_REQUEST;
public static final ProtoBufType HTTP_RESPONSE;




ProtoBufStreamConfiguration定义了同的XML Packet类型对应的字节值


public static final byte HEARTBEAT_PING_TAG = 0;
public static final byte HEARTBEAT_ACK_TAG = 1;
public static final byte LOGIN_REQUEST_TAG = 2;
public static final byte LOGIN_RESPONSE_TAG = 3;
public static final byte CLOSE_TAG = 4;
public static final byte MESSAGE_TAG = 5;
public static final byte PRESENCE_TAG = 6;
public static final byte IQ_TAG = 7;
public static final byte DATA_MESSAGE = 8;
public static final byte BATCH_PRESENCE = 9;
public static final byte STREAM_ERROR = 10;
public static final byte HTTP_REQUEST = 11;
public static final byte HTTP_RESPONSE = 12;




[b]2. Parse的流程[/b]


Smack中的PacketReader类是用来从XMPPConnection上读取Packets的. 它会首先判断useProtoBuf标志. 如果是true, 则使用ProtoBufStreamParser作为parser来解析数据流; 否则, 则使用XmlPullParser作为parser来解析数据流.



ProtoBufStreamParser的主要方法为:


public abstract void parse(ByteBuffer byteBuffer)
     throws ProtoBufStreamException, IOException;



ProtoBufStreamParser其实主要是分析数据流的前几个字节获得Packets的类型(message, presence等), 然后会调用ProtoBufEventHandler的handleProtoBuf()方法.


public interface ProtoBufEventHandler {
  public abstract void handleProtoBuf(ProtoBuf protoBuf, long paramLong);
}



而PacketReader实际上实现了ProtoBufEventHandler接口, 所以在PacketReader的handleProtoBuf()方法中进一步解析protobuf数据流, 根据不同的类型创建不同的Packet对象, 比如Message对象, Presence对象等.



[b]3. Serialize的流程[/b]


Smack中的PacketWriter类是用来构建Packets然后写到XMPPConnection上的. 它会首先判断useProtoBuf标志. 如果是true, 则调用serializeAsProtoBuf()来形成数据流; 否则, 调用serializeAsXml()来形成数据流.


serializeAsProtoBuf()方法会调用toProtoBuf(),就像serializeAsXml()会调用toXML().


因此每种Packets类型都需要实现toProtoBuf()和toXML().


public abstract class Packet {
    public abstract ProtoBuf toProtoBuf();
    public abstract String toXML();
}

public class Message extends Packet {
    public ProtoBuf toProtoBuf() {
        ProtoBufType protoBufType = GtalkCoreMessageTypes.MESSAGE_STANZA;
        ProtoBuf protoBuf = new ProtoBuf(protoBufType);
        protoBuf.setString(MessageStanza.ID, getPacketID());
        protoBuf.setString(MessageStanza.TO, getTo());
        protoBuf.setString(MessageStanza.FROM, getFrom());
        protoBuf.setInt(MessageStanza.TYPE, Type.CHAT);
        protoBuf.setInt(MessageStanza.SUBJECT,  this.subject);
        protoBuf.setInt(MessageStanza.BODY,  this.body);
        ......
    }

    public String toXML() {
         StringBuffer buf = new StringBuffer();
         buf.append("<message");
         buf.append(" id=\"").append(getPacketID()).append("\"");
         buf.append(" to=\"").append(getTo()).append("\"");
         buf.append(" from=\"").append(getFrom()).append("\"");
         buf.append(" type=\"").append(Type.CHAT).append("\"");
         ......
         buf.append(">");
         buf.append("<subject>").append(this.subject).append("</subject>")
         buf.append("<body>").append(this.body).append("</body>")
         ......
         return buf.toString();
    }
}

public class Presence extends Packet {
    public ProtoBuf toProtoBuf() {
        ......
    }

    public String toXML() {
         ......
    }
}




serializeAsProtoBuf()方法首先通过调用Packets的toProtoBuf()获得protobuf后, 会再调用ProtoBufStreamSerializer的serialize()方法, 在serialize()方法中会把Packets类型对应的字节值加到protobuf前面.


public interface ProtoBufStreamSerializer {
    public void serialize(ProtoBuf protoBuf, OutputStream outputStream)
      throws ProtoBufStreamException, IOException;

    public byte[] serialize(ProtoBuf protoBuf)
      throws ProtoBufStreamException, IOException;
}

标签:XML,protobuf,public,static,ProtoBufType,格式,byte,final
From: https://blog.51cto.com/u_16125990/6405086

相关文章

  • Spring Boot 使用 Dom4j XStream 操作 Xml
    阅读目录 0Dom4jXStream简单介绍Dom4jXStream1新建SpringBootMaven示例工程项目2引入依赖Pom3Dom4j代码实例3.1打开一个远程xml3.2创建一个xml文档3.3遍历3.4使用xpath获取节点3.5保存到文件3.6XML文件转文本3.7文本转XML文档对象3.8使用XSLT转换......
  • C++字符串分割和C语言常用格式控制
    C++string的输出格式控制输出一个字符串:左对齐,字宽为10,空格填充1.strings;2.cin>>s;3.cout<<std::left<<setw(10)<<setfill('*')<<s<<endl;输入:love输出效果:love******C++string字符流字符分割技巧输入一行字符串,然后按某个字符分割成若干子串1.strings;......
  • ogg格式怎样才能转换成mp3
    对于一些非常喜欢下载视频的朋友来说,相信应该对视频和音频的格式转换都非常关心吧,但是大家可能并知道到怎么才能更好的转换视频的格式,下面小编就以ogg格式怎么转换成mp3为例给大家详细的介绍一下,想知道的小伙伴们快来看下吧。Ogg是一种音频压缩格式,类似于MP3等的音乐格式。但是......
  • springboot项目rabbitmq消费者消费json格式的String,出现无限循环抛出No method found
    转:springboot项目rabbitmq消费者消费json格式的String,出现无限循环抛出Nomethodfoundforclass[B     ......
  • Spring Boot实现xml传参和返回值
    阅读文本大概需要3分钟。    虽然json作为数据传输的格式大型其道,但是使用xml格式传输的系统还是在一些存量的系统中存在。另外WebService本身就是使用xml格式进行数据传输。今天用个小例子看看SpringBoot如何实现xml传参和返回值。1、新建maven项目,添加依赖1.<projectxm......
  • Android strings.xml按照key修改
    strings.xml匹配替换将两个Android项目中的多语言字符串文件(strings.xml)进行比较,如果其中一个项目中包含另一个项目没有的字符,则合并到单一的输出文件,并以key在原始XML文件中更新value值。如果key匹配不准确则忽略它。具体来说:引入re,xml.etree.ElementTree和argpar......
  • 前端预览docx格式文档
    运用docx-preview.js(去网上下载https://github.com/VolodymyrBaydalka/docxjs/blob/master/dist/docx-preview.js)引入脚本<scripttype="text/javascript"src="https://unpkg.com/promise-polyfill/dist/polyfill.min.js"></script&......
  • Excel转CSV格式
    注意:CSV文件导出来的可以理解为就是一个普通的文件,但至于使用什么样的软件打开就是另一马事了,比如Excel打开后出来“自动过滤了数字前面的0”,这玩意程序控制不到,那是Excel的事情。CSV不是Excel文件切记,只不过用表格软件打开CSV而已importorg.apache.poi.hssf.usermodel.HSS......
  • Pandas中将字符串(object)格式的列,强制转换为浮点型的列
    importpandasaspddf=pd.DataFrame([['11.0',1,2,3],['22.0',4,5,6],['33.0',7,8,9]],columns=['a','b','c','d'])df['a']=pd.......
  • 论文的格式要求和字体大小
    在社会的各个领域,大家都写过论文吧,借助论文可以有效提高我们的写作水平。写论文的注意事项有许多,你确定会写吗?下面是小编为大家收集的论文的格式要求和字体大小,仅供参考,希望能够帮助到大家。论文的格式要求和字体大小一、封面题目:小二号黑体加粗居中。各项内容:四......