smack 源码分析- PacketWriter (android上兑现长连接)

转载自:http://www.myexception.cn/android/445475.html


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

上一篇smack 源码分析一(android上实现长连接)  整体分析了smack长连接的流程, 本篇将详细介绍PacketWriter.

PacketWriter是在上篇在介绍initConnection()方法中创建的,那么详细看下PacketWriter的实现: 

protected PacketWriter(XMPPConnection connection) {
        this.queue = new ArrayBlockingQueue<Packet>(500, true);
        this.connection = connection;
        init();
 }




protected void init() {
        this.writer = connection.writer;
        done = false;
        lastActive = System.currentTimeMillis();
        
        //开辟一个写网络流数据线程
        writerThread = new Thread() {
            public void run() {
                writePackets(this);
            }
        };

        writerThread.setName("Smack Packet Writer (" + connection.connectionCounterValue + ")");
        writerThread.setDaemon(true);

    }



/**
     * 向网络流写数据包
     * @param thisThread
     */
    private void writePackets(Thread thisThread) {
        try {
            // Open the stream.
            openStream();
            // Write out packets from the queue.
            while (!done && (writerThread == thisThread)) {
                Packet packet = nextPacket();
                if (packet != null) {
                    synchronized (writer) {
                        writer.write(packet.toXML());
                        writer.flush();
                        // Keep track of the last time a stanza was sent to the
                        // server
                        lastActive = System.currentTimeMillis();
                    }
                }
            }

            synchronized (writer) {
                while (!queue.isEmpty()) {
                    Packet packet = queue.remove();
                    writer.write(packet.toXML());
                }
                writer.flush();
            }

            queue.clear();
            writer.write("</stream:stream>");
            writer.flush();

        } catch (IOException ioe) {
            if (!done) {
                done = true;
                connection.packetReader.notifyConnectionError(ioe);
            }
        } finally {
            try {
                if (writer != null) {
                    writer.close();
                }
            } catch (Exception e) {
            }
        }
    }

 

在PacketWriter构造方法中传递参数XMPPConnection作为PacketWriter成员变量, 然后调用init()方法 ,而在init()方法中, 开辟一个线程专门用于向服务器写数据. writerPackets()里面是一个无限循环体, 不断的从消息队列queue读取pakcet消息读取完之后调用wirter.flush()方法, 将消息发送的服务器. 这个过程就完成了终端完服务器发送消息的过程. 

 

接下来是, 终端如何与云端保持连接呢, 那肯定是发送心跳包咯. 我们来看下PacketWriter是如何发送心跳包的:

 

/**
     * A TimerTask that keeps connections to the server alive by sending a space
     * character on an interval.
     */
    private class KeepAliveTask implements Runnable {

        private int delay;
        private Thread thread;

        public KeepAliveTask(int delay) {
            this.delay = delay;
        }

        protected void setThread(Thread thread) {
            this.thread = thread;
        }
        
        public void run() {
            try {
                // Sleep 15 seconds before sending first heartbeat. This will give time to
                // properly finish TLS negotiation and then start sending heartbeats.
                Thread.sleep(15000);
            }
            catch (InterruptedException ie) {
                // Do nothing
            }
            while (!done && keepAliveThread == thread) {
                synchronized (writer) {
                    // Send heartbeat if no packet has been sent to the server for a given time
                    if (System.currentTimeMillis() - lastActive >= delay) {
                        try {
                            writer.write(" ");
                            writer.flush();
                        }
                        catch (Exception e) {
                            // Do nothing
                        }
                    }
                }
                try {
                    // Sleep until we should write the next keep-alive.
                    Thread.sleep(delay);
                }
                catch (InterruptedException ie) {
                    // Do nothing
                }
            }
        }
    }

 

心跳发送类: KeepAliveTask 是一个自定义线程, 它定义了心跳发送的时间间隔, 在其run方法里面一个无限循环体每隔delay毫秒就向云端发发送一个空消息(当然, 如需要你可以根据项目需求自定义一个心跳包). 整个PacketWriter介绍基本到此结束, 在你应用登陆成功之后就可以开启KeepAliveTask 线程定时发送心跳包到服务器保持终端与服务器的长连接.


Smack是一个开源的XMPP客户端库,可用于在Android平台上构建即时通信应用程序。在使用SmackAndroid应用程序中,需要使用Smack-Android库来处理网络和连接管理。 以下是一个简单的示例代码,演示如何使用Smack-Android库连接到XMPP服务器并发送消息: 1. 添加依赖库 在项目的build.gradle文件中添加以下依赖: ``` dependencies { implementation 'org.igniterealtime.smack:smack-android-extensions:4.4.0' implementation 'org.igniterealtime.smack:smack-tcp:4.4.0' } ``` 2. 初始化连接 在应用程序启动时,需要初始化XMPPConnection对象,并且连接到XMPP服务器。 ``` XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder() .setUsernameAndPassword("username", "password") .setXmppDomain("example.com") .setHost("xmpp.example.com") .setPort(5222) .setSecurityMode(ConnectionConfiguration.SecurityMode.required) .build(); XMPPTCPConnection connection = new XMPPTCPConnection(config); try { connection.connect(); connection.login(); // Connection successful } catch (SmackException | IOException | XMPPException e) { e.printStackTrace(); // Connection failed } ``` 3. 发送消息 连接成功后,可以使用XMPPConnection对象发送消息。 ``` ChatManager chatManager = ChatManager.getInstanceFor(connection); Chat chat = chatManager.createChat("recipient@example.com"); try { chat.sendMessage("Hello, World!"); } catch (SmackException.NotConnectedException | InterruptedException e) { e.printStackTrace(); } ``` 这是一个简单的Smack-Android示例,用于连接到XMPP服务器并发送消息。当然,在实际应用程序中可能需要更多的功能和处理,但这个示例提供了一个入门的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值