`

smack 源码分析- PacketReader (android上实现长连接)

阅读更多

smack 源码分析- PacketWriter (android上实现长连接) 介绍完PacketWriter 之后, 接下来分析PacketReader. 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 接口决定哪个特别的将会被传递 PacketCollectorPacketListener。org.jivesoftware.smack.filter package包中有许多预定义的过滤器。


packetListener 是一个能够处理随时可能到了的packet监听器, packetFilter能够判断packet是否由该packetListener处理

是的话则调用processPacket()方法处理packet. 至此整个过程处理完成

 

 

分享到:
评论
2 楼 337240552 2012-10-29  
1 楼 flytosea 2012-03-30  
写的很不错 学习了 

相关推荐

Global site tag (gtag.js) - Google Analytics