`

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

阅读更多
http://code.google.com/p/protobuf/

先介绍下什么是protobuf以及有什么好处.
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.

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

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

Android上GTalk以及Push机制的XMPP数据选择使用protobuf格式
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为对象数据.

1. 针对不同的XML Packet类型用不同的字节值表示.

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;


2. Parse的流程
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对象等.

3. Serialize的流程
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;
}



分享到:
评论
1 楼 xici_magic 2011-02-16  
这个也是跨平台?

相关推荐

    android push开发

    接下来说说XMPP在android客户端上的应用。分两部分:服务端搭建和客户端实现。 服务端搭建: 点击bin目录下得run.bat,直接搭好服务,在浏览器上输入 http://127.0.0.1:7070 ,可以修改配置在conf/config....

    GTalkSMS源码

    然后你就可以用你的主控端发送消息的方式控制你的手机 "&gt;GTalkSMS实现了一个xmpp机器人 只要你在自己的gtalk(xmpp)上增加这个机器人为好友 就能像聊天一样远程操作自己的android手机了 使用简单就像是在即时聊天...

    android Gtalk.apk

    Google Talk(Gtalk)是Google公司开发的即时通讯工具,Gtalk除了具备一般IM功能外,还加上了Viop功能,Gtalk界面清晰大方,可直接链接Gmail,轻松接受邮件。欢迎下载最新版google talk。

    Android中的XMPP应用

    XMPP是由Jabber开源社区贡献的一个基于XML的通信协议,它是被广泛应用的四大即时通信协议之一。Google的即时通信软件GTalk就是基于XMPP协议的。这次Google推出Android应用了XMPP,为它编写了相应的API和Demo。本文件...

    XMPP DEMO android4.0通过

    XMPP DEMO android4.0通过, 2.3无法启动

    gtalk.apk-android

    gtalk.apk-android

    gtalk-rpg:通过 gTalk 或其他基于 XMPP 的 IM 服务玩桌面 RPG-开源

    通过 gTalk 或其他基于 XMPP 的 IM 服务玩桌面 RPG。 ========== 通过 gTalk 或其他基于 XMPP 的 IM 服务玩桌面 RPG。 当今可用于在线角色扮演角色扮演的大多数程序都是使用私有服务器的专有应用程序。 如果服务器...

    ft.zip_gloox_gtalk_visual c_xmpp

    gloox 文件传输 xmpp协议 传输文件

    ch25_gtalk.rar_android_ch25_gtalk_gtalk_gtalk andro

    android 仿gtalk 源代码 挺有意思的 可以参考借鉴下

    完美解决android电子市场不能下载,Gtalk、Gmail不能正常使用

    完美解决android电子市场不能下载,Gtalk、Gmail不能正常使用……弄法见内部操作指南

    Android入门到精通源代码.

    9.1.2 使用XML存储Preferences数据 9.2 使用文件存储数据 9.2.1 访问应用中的文件数据 9.2.2 访问设备中独立的文件数据 9.3 使用SQLite数据库存储数据 9.3.1 SQLite数据库简介 9.3.2 SQLite数据库操作 9.3.3 使用...

    gtalksms源码1

    然后你就可以用你的主控端发送消息的方式控制你的手机 "&gt;GTalkSMS实现了一个xmpp机器人 只要你在自己的gtalk(xmpp)上增加这个机器人为好友 就能像聊天一样远程操作自己的android手机了 使用简单就像是在即时聊天...

    新版Android开发教程.rar

    的 Android SDK 提供了在 Android 平台上使用 JaVa 语言进行 Android 应用开发必须的工具和 API 接口。 特性 • 应用程序框架 支持组件的重用与替换 • Dalvik Dalvik Dalvik Dalvik 虚拟机 专为移动设备优化 • ...

    Android高级编程--源代码

    由于现有的手机应用程序的开发是构建在各手机厂家的私有操作系统之上的,所以它限制了第三方应用程序的开发,而Android为我们提供了一个开放和通用的选择。因为没有了人为制造的障碍,所以Android开发人员可以自由地...

    Android 中文API合集(4)(102篇)(chm格式)

    API文档(Reference)是Android开发的基础,Android中文翻译组聚一批开发人员、大学生、研究生等Android爱好者,利用业余时间对API进行翻译,欢迎更多朋友加入,联系我们:QQ:36408253,Gtalk:over140@gmail.com,...

    GTalk 绿色单文件版

    GTalk 绿色单文件版

    Android 中文API chm格式合集(3)(83篇)——原版

    Android中文翻译组迎来了第三个chm格式合集,收集整理83篇已发表译文制作成合集,参与成员有0_1、桂仁、cofice、唐明、loveshirui 、madgoat 、颖哥儿、思考的狼、德罗德、henly.zhang、wallace2010、Tina、首当其冲...

    华为C8500 (gtalk)google_talk apk android 2.1平台

    难得资源,gtalk是google聊天工具,挂着几乎没有流量,发消息与接消息占多少用多少流浪,飞信比QQ省流量,精简飞信比飞信省流量,gtalk比精简飞信还省流量。挂着用吧。热爱网络,珍惜收藏

    gtalk样式自定义方法

    gtalk样式自定义方法

    《Android高级编程》

    第9章 P2P通信 9.1 Android即时消息简介 9.1.1 使用GTalk服务 9.1.2 和GTalk服务绑定 9.1.3 建立GTalk连接,开始一个IM会话 9.1.4 在线状态和联系人列表简介 9.1.5 管理聊天会话 9.1.6 发送和接收数据信息 9.2 SMS...

Global site tag (gtag.js) - Google Analytics