`

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  
写的很不错 学习了 

相关推荐

    Android使用smack连接ejabberd服务器注册、收发消息

    implementation 'org.igniterealtime.smack:smack-android-extensions:4.3.5' implementation 'org.igniterealtime.smack:smack-tcp:4.3.5' implementation 'org.igniterealtime.smack:smack-im:4.3.5' ...

    smack-resolver-dnsjava-4.0.0-rc2.zip

    综上所述,"smack-resolver-dnsjava-4.0.0-rc2.zip" 包含了 Smack 的一个版本,它利用 DNSJava 实现了对 XMPP 服务器的智能解析。同时,描述中的 Peon 可能是一个辅助 XMPP 服务器管理的工具,同样使用 Java 编写。...

    smack-resolver-javax-4.1.0-alpha6.zip

    标题中的"smack-resolver-javax-4.1.0-alpha6.zip"是一个软件库的压缩包,Smack是一款开源的XMPP客户端库,而"javax"可能指的是它提供了与Java平台兼容的解析器组件。这个版本是4.1.0的Alpha6,意味着它是一个开发...

    smack4.1.6连接openfire,tigase,ejabberd所需jar包

    jxmpp-core-0.5.0-alpha7 jxmpp-util-cache-0.5.0-alpha7 smack-android-4.1.6 smack-core-4.1.6 smack-extensions-4.1.6 smack-im-4.1.6 smack-sasl-provided-4.1.6 smack-tcp-4.1.6

    smack-resolver-minidns-4.1.0-alpha3.jar

    smack4.1.0的依赖包minidns.jar。可用于smack4.1.3,亲测可用!

    smack-core-4.0.0.zip

    本压缩包"smack-core-4.0.0.zip"包含了Smack Core 4.0.0版本的源代码,这是一个著名的Java即时通讯(Instant Messaging)库,主要用于实现XMPP协议。Smack为开发者提供了丰富的API,使得构建XMPP应用变得更加便捷。 ...

    android smack源码

    **Android Smack源码解析** ...总之,Android Smack源码是一个深入了解XMPP协议和即时通讯实现的宝贵资源,对于需要构建IM应用的开发者来说,深入研究这个库将大大提升他们的专业技能和解决问题的能力。

    smack-jar Android

    总之,Smack-JAR是Android开发者构建即时通讯应用的强大工具,通过理解和熟练运用其API,可以实现丰富的通讯功能,如一对一聊天、群聊、文件传输等。同时,还需要关注Android平台的特性,确保应用的稳定性和用户体验...

    smack4.3.1

    总结,Smack 4.3.1是一个强大的Android即时通讯框架,它为开发者提供了实现XMPP协议所需的全部工具,通过合理的使用和配置,可以构建出高效、稳定的IM应用。结合Openfire等服务器,可以构建出企业级的通讯解决方案。

    android smack客户端

    implementation 'org.igniterealtime.smack:smack-android-extensions:4.4.3' implementation 'org.igniterealtime.smack:smack-tcp:4.4.3' implementation 'org.igniterealtime.smack:smack-im:4.4.3' ...

    android_smack4.1.9-demo

    自4.1.0版本起,Smack开始全面支持Android平台,使得开发者能够方便地在Android设备上构建功能丰富的聊天应用程序。在"android_smack4.1.9-demo"项目中,我们能看到如何在Android Studio环境下集成并使用Smack 4.1.9...

    smack-1.0-master

    这个"smack-1.0-master"压缩包包含的是Smack工具的源代码,主要版本为1.0,并且经过了特定的修改,能够支持`.smackcipso`、`smackload`、`smackaccess`和`smackctl`等工具的使用。下面将详细介绍这些工具和Smack系统...

    smack-extensions-4.1.0-alpha3.zip

    【标题】"smack-extensions-4.1.0-alpha3.zip" 提供的是 Smack 开源库的一个扩展包,版本为4.1.0的Alpha3版本。Smack 是一个用于XMPP(Extensible Messaging and Presence Protocol)的Java库,它允许开发者在Java...

    Android-Openfire-Smack4.1.2 (Android Studio)

    implementation 'org.igniterealtime.smack:smack-android-extensions:4.3.5' implementation 'org.igniterealtime.smack:smack-tcp:4.3.5' implementation 'org.igniterealtime.smack:smack-extensions:4.3.5' }...

    Smack源码,很有用

    通过分析和学习Smack源码,不仅可以掌握XMPP协议的实现细节,还能提升对Java网络编程、XML处理、事件驱动编程的理解,为开发实时通信应用打下坚实基础。同时,这也有助于理解其他基于XMPP的项目,如ejabberd服务器或...

    smack-im-4.3.4-sources_www.im.43_im_

    【标题】"smack-im-4.3.4-sources_www.im.43_im_" 指的是 Smack IM 的4.3.4版本的源代码,这个开源项目主要关注即时通讯(IM)功能的实现。Smack是一个用Java编写的库,允许开发者在他们的应用程序中集成XMPP...

    asmack-android-16-source-beem.zip

    asmack-android-16-beem.jar是一个编译后的Java类库,而这里的源码提供了一窥其实现细节的机会,对于开发者来说,这有助于理解Beem如何利用Asmack在Android平台上实现其功能。 标签“asmack”,“android 16”,...

Global site tag (gtag.js) - Google Analytics