Smack 开源库学习总结(二)连接服务器

Smack 开源库学习总结(二)连接服务器

结合开源代码,深入学习几个重点函数的具体实现功能。

本篇文章主要学习 XMPPTCPConnection中函数conncect()的具体实现的功能。

XMPPTCPConnection connection = new XMPPTCPConnection(config);
connection .connect();

XMPPConnection.java是一个接口,里面定义了获取服务器name、host、及port等等方法。
AbstractXMPPConnection.java抽象类实现了XMPPConnection.java这个接口,XMPPTCPConnection.java和XMPPBOSHConnection.java是继承AbstractXMPPConnection.java,以实现不同的功能。

connect()在AbstractXMPPConnection.java中实现,其只是连接服务器的总入口而已。

public synchronized AbstractXMPPConnection connect() throws SmackException, IOException, XMPPException, InterruptedException {
        // Check if not already connected
        throwAlreadyConnectedExceptionIfAppropriate();

        // Reset the connection state
        initState();
        saslAuthentication.init();
        streamId = null;

        try {
            // Perform the actual connection to the XMPP service
            connectInternal();

            // If TLS is required but the server doesn't offer it, disconnect
            // from the server and throw an error. First check if we've already negotiated TLS
            // and are secure, however (features get parsed a second time after TLS is established).
            if (!isSecureConnection() && getConfiguration().getSecurityMode() == SecurityMode.required) {
                throw new SecurityRequiredByClientException();
            }
        } catch (SmackException | IOException | XMPPException | InterruptedException e) {
            instantShutdown();
            throw e;
        }

        // Make note of the fact that we're now connected.
        connected = true;
        callConnectionConnectedListener();

        return this;
    }

实际连接服务器的动作是由抽象函数connectInternal()处理,在XMPPTCPConnection中实现了connectInternal()具体动作,该函数主要实现
(1) 函数connectUsingConfiguration() 实现 XMPP Server建立Socket连接;
(2) 函数initConnection() 实现初始化数据写入和读取的操作流程。

    protected void connectInternal() throws SmackException, IOException, XMPPException, InterruptedException {
        closingStreamReceived.init();
        // Establishes the TCP connection to the server and does setup the reader and writer. Throws an exception if
        // there is an error establishing the connection
        connectUsingConfiguration();

        // We connected successfully to the servers TCP port
        initConnection();

        // TLS handled will be successful either if TLS was established, or if it was not mandatory.
        tlsHandled.checkIfSuccessOrWaitOrThrow();

        // Wait with SASL auth until the SASL mechanisms have been received
        saslFeatureReceived.checkIfSuccessOrWaitOrThrow();
    }

在initConnection()中初始化数据流读写线程:packetWriter.init() 和 packetReader.init();

private void initConnection() throws IOException, InterruptedException {
        compressionHandler = null;

        // Set the reader and writer instance variables
        initReaderAndWriter();

        int availableReaderWriterSemaphorePermits = readerWriterSemaphore.availablePermits();
        if (availableReaderWriterSemaphorePermits < 2) {
            Object[] logObjects = new Object[] {
                            this,
                            availableReaderWriterSemaphorePermits,
            };
            LOGGER.log(Level.FINE, "Not every reader/writer threads where terminated on connection re-initializtion of {0}. Available permits {1}", logObjects);
        }
        readerWriterSemaphore.acquire(2);
        // Start the writer thread. This will open an XMPP stream to the server
        packetWriter.init();
        // Start the reader thread. The startup() method will block until we
        // get an opening stream packet back from server
        packetReader.init();
    }

在数据流写入初始化函数packetWriter.init()中,开启线程 writePackets(),并将数据流保存在packetReader.parser 中;

在数据读取初始化函数packetReader.init()中,开启线程parsePackets()对packetReader.parser中的数据进行解析处理;

private void parsePackets() {
            try {
                initialOpenStreamSend.checkIfSuccessOrWait();
                int eventType = parser.getEventType();
                while (!done) {
                    switch (eventType) {
                    case XmlPullParser.START_TAG:
                        final String name = parser.getName();
                        switch (name) {
                        case Message.ELEMENT:
                        case IQ.IQ_ELEMENT:
                        case Presence.ELEMENT:
                            try {
                                parseAndProcessStanza(parser);
                            } finally {
                                clientHandledStanzasCount = SMUtils.incrementHeight(clientHandledStanzasCount);
                            }
                            break;
                        case "stream":
                            // We found an opening stream.
                            if ("jabber:client".equals(parser.getNamespace(null))) {
                                streamId = parser.getAttributeValue("", "id");
                                String reportedServerDomain = parser.getAttributeValue("", "from");
                                assert (config.getXMPPServiceDomain().equals(reportedServerDomain));
                            }
                            break;
                        case "error":
                            StreamError streamError = PacketParserUtils.parseStreamError(parser);
                            saslFeatureReceived.reportFailure(new StreamErrorException(streamError));
                            // Mark the tlsHandled sync point as success, we will use the saslFeatureReceived sync
                            // point to report the error, which is checked immediately after tlsHandled in
                            // connectInternal().
                            tlsHandled.reportSuccess();
                            throw new StreamErrorException(streamError);
                        case "features":
                            parseFeatures(parser);
                            break;
                            .......(下面代码省略)
                        }
                    }
                } 
            }
        }    

连接成功后,回调connected(),表明已经和服务器连接成功。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值