当前位置:首页 > 开发 > 移动开发 > 正文

smack - PacketReader

发表于: 2013-03-07   作者:追求幸福   来源:转载   浏览次数:
摘要: 转自: http://blog.csdn.net/wqhjfree/article/details/7194428 PacketReader的作用主要用来接收云端推送的消息并解析然后调用相应的监听器完成相关的操作. 什么都别说, 先看代码: //构造函数 protected PacketReader(final XMPPConnection connection) {
转自: http://blog.csdn.net/wqhjfree/article/details/7194428

PacketReader的作用主要用来接收云端推送的消息并解析然后调用相应的监听器完成相关的操作.
什么都别说, 先看代码:
//构造函数
protected PacketReader(final XMPPConnection connection) {
        this.connection = connection;
        this.init();
}


 /**
     * Initializes the reader in order to be used. The reader is initialized
     * during the first connection and when reconnecting due to an abruptly
     * disconnection.
     */
    protected void init() {
        done = false;
        connectionID = null;

        //开辟一个线程, 解析收到的数据包
        readerThread = new Thread() {
            public void run() {
                parsePackets(this);
            }
        };
        readerThread.setName("Smack Packet Reader (" + connection.connectionCounterValue + ")");
        readerThread.setDaemon(true);

        // Create an executor to deliver incoming packets to listeners. We'll
        // use a single
        // thread with an unbounded queue.
        listenerExecutor = Executors.newSingleThreadExecutor(new ThreadFactory() {

            public Thread newThread(Runnable runnable) {
                Thread thread = new Thread(runnable, "Smack Listener Processor ("
                        + connection.connectionCounterValue + ")");
                thread.setDaemon(true);
                return thread;
            }
        });

        resetParser();
    }




 /**
     * Parse top-level packets in order to process them further.
     * 
     * @param thread the thread that is being used by the reader to parse
     *            incoming packets.
     */
    private void parsePackets(Thread thread) {
        try {
            int eventType = parser.getEventType();
            do {

                if (eventType == XmlPullParser.START_TAG) {
                    if (parser.getName().equals("message")) {
                        processPacket(PacketParserUtils.parseMessage(parser));
                    } else if (parser.getName().equals("iq")) {
                        processPacket(PacketParserUtils.parseIQ(parser, connection));
                    } else if (parser.getName().equals("presence")) {
                        processPacket(PacketParserUtils.parsePresence(parser));
                    }


构造函数和init()方法PacketWriter一样, 不多说了. 直接看parsePackets(). 在parsePackets()是直接调用processPacket()方法解析, 我们再来看processPacket()方法:
/**
     * Processes a packet after it's been fully parsed by looping through the
     * installed packet collectors and listeners and letting them examine the
     * packet to see if they are a match with the filter.
     * 
     * @param packet the packet to process.
     */
    private void processPacket(Packet packet) {
        if (packet == null) {
            return;
        }

        // Loop through all collectors and notify the appropriate ones.
        for (PacketCollector collector : connection.getPacketCollectors()) {
            collector.processPacket(packet);
        }

        // Deliver the incoming packet to listeners.
        listenerExecutor.submit(new ListenerNotification(packet));
    }


在processPacket()的最后一行是通过ExecutorService类型的一个listenerExecutor实例执行一个线程ListenerNotification完成的. 接下来:
/**
     * A runnable to notify all listeners of a packet.
     */
    private class ListenerNotification implements Runnable {

        private Packet packet;

        public ListenerNotification(Packet packet) {
            this.packet = packet;
        }

        public void run() {
        	//循环读取注册了的监听器并通知处理packet
            for (ListenerWrapper listenerWrapper : connection.recvListeners.values()) {
            	
                listenerWrapper.notifyListener(packet);
            }
        }
    }


在ListenerNotification的run方法中,  是循环读取connection.recvListeners.values()获取ListenerWrapper
.
那么ListenerWrapper 是什么呢? 我们首先来看这里connection.recvListeners.values(),
这connection实际上
是一个XMPPConnection的一个实例, 而XMPPConnection继承了Connection, recvListeners实际上是Connection
的一个成员变量. 然后再来看ListenerWrapper类:
/**
     * A wrapper class to associate a packet filter with a listener.
     *
     */
    protected static class ListenerWrapper {

        private PacketListener packetListener;

        private PacketFilter packetFilter;

        /**
         * Create a class which associates a packet filter with a listener.
         * 
         * @param packetListener the packet listener.
         * @param packetFilter the associated filter or null if it listen for
         *            all packets.
         */
        public ListenerWrapper(PacketListener packetListener, PacketFilter packetFilter) {
            this.packetListener = packetListener;
            this.packetFilter = packetFilter;
        }

        /**
         * Notify and process the packet listener if the filter matches the
         * packet. 
         * @param packet the packet which was sent or received.
         */
        public void notifyListener(Packet packet) {
            if (packetFilter == null || packetFilter.accept(packet)) { 
                packetListener.processPacket(packet);
            }
        }
    }


ListenerWrapper类实际上是一个包装类, 该类的作用是将packetListener 和packetFilter关联在一起.
那么
packetListener 和packetFilter分别是什么嗯,
查看smack帮助文档可知:

Smack提供灵活的框架来通过两种构造处理收到的 packet:
org.jivesoftware.smack.PacketCollector —— 一个让您同步等待新packet的类。
org.jivesoftware.smack.PacketListener —— 一个异步通知您引入的packet的接口。
packet监听器用于事件样式的编程,而packet收集器有一个可以做轮询和阻塞操作的packet的结果队列。 所以,
当您想对一个有可能随时到来的packet采取一些操作时,使用packet监听器;而当您想等待一个特别的packet到来
时,使用packet收集器。您可以使用XMPPConnection实例创建packet收集器和监听器。
org.jivesoftware.smack.filter.PacketFilter 接口决定哪个特别的将会被传递
到PacketCollector或PacketListener。org.jivesoftware.smack.filter package包中有许多预定义的过滤器。

packetListener 是一个能够处理随时可能到了的packet监听器,packetFilter能够判断packet是否由该packetListener处理
是的话则调用processPacket()方法处理packet. 至此整个过程处理完成

smack - PacketReader

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
OpenFire 是采用Java开发的基于XMPP(Jabber)协议,开源实时协作(RTC)服务器。 Smack 是用 Java
OpenFire 是采用Java开发的基于XMPP(Jabber)协议,开源实时协作(RTC)服务器。 Smack 是用 Java
OpenFire 是采用Java开发的基于XMPP(Jabber)协议,开源实时协作(RTC)服务器。 Smack 是用 Java
openfire的文件发送有两种: XMPP支持两种文件流传输协议,SOCKS5 Bytestreams和 In-Band Bytestrea
smack是什么?具体百度一下。我的理解也不深,我理解其实就是XMPP协议的实现。都是浮云,一切都是工
XmpPullParser   鉴于xmpp协议都是以xml格式来传输,因此源码中解析协议都是用到XmpPullParser来
基于openfire_3_10_0、smack_4_1_1 的聊天推送demo. 前提:在最新版本中通过smack类库实现聊天内容
1:关于smack与tigase的用法跟作用请大家自己去网上查看相关资料,这里就不做描述了。 PS:这篇文章
上一篇:基于xmpp openfire smack开发openfire之介绍和部署[1] 关于Smack编程库,前面我们提到,它
本文转载http://blog.csdn.net/shimiso 关于Smack编程库,前面我们提到,它是面向Java端的api,主要
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号