XMPP協議學習筆記五(Openfire訊息處理流程)

來源:互聯網
上載者:User

     XMPP協議作為一個IM,其核心在於訊息的傳遞,在Openfire伺服器對XMPP的實現中,訊息被封裝為Packet對象,因此Openfire伺服器的核心代碼是對用戶端Packet對象的監聽和處理流程,我們今天就來研究一下Openfire的訊息包接受處理流程。

     首先,Openfire伺服器需要啟動一個基於TCP/IP的監聽服務,用以接收用戶端傳過來的XML流檔案。這個過程在XMPPServer類的start()方法中進行,這個監聽服務是以loadModule(ConnectionManagerImpl.class.getName())來載入,調用ConnectionManagerImpl類的createClientListeners()方法

    private void createClientListeners() {        // Start clients plain socket unless it's been disabled.        if (isClientListenerEnabled()) {            // Create SocketAcceptor with correct number of processors            socketAcceptor = buildSocketAcceptor();            // Customize Executor that will be used by processors to process incoming stanzas            ExecutorThreadModel threadModel = ExecutorThreadModel.getInstance("client");            int eventThreads = JiveGlobals.getIntProperty("xmpp.client.processing.threads", 16);            ThreadPoolExecutor eventExecutor = (ThreadPoolExecutor)threadModel.getExecutor();            eventExecutor.setCorePoolSize(eventThreads + 1);            eventExecutor.setMaximumPoolSize(eventThreads + 1);            eventExecutor.setKeepAliveTime(60, TimeUnit.SECONDS);            socketAcceptor.getDefaultConfig().setThreadModel(threadModel);            // Add the XMPP codec filter            socketAcceptor.getFilterChain().addFirst("xmpp", new ProtocolCodecFilter(new XMPPCodecFactory()));            // Kill sessions whose outgoing queues keep growing and fail to send traffic            socketAcceptor.getFilterChain().addAfter("xmpp", "outCap", new StalledSessionsFilter());        }    }
其中的socketAcceptor是在buildSocektAcceptor()方法中定義的,它是作為一個服務端的接收器,是mina架構為我們封裝好的一個socketserver,在上面這個方法中,我們為socketAcceptor添加了一個過濾器,XMPPCodeFactory,這個類將過濾xmpp相關請求,加以處理,我們再看同一個類的另外一個方法startClientListener()
     private void startClientListeners(String localIPAddress) {        // Start clients plain socket unless it's been disabled.        if (isClientListenerEnabled()) {            int port = getClientListenerPort();            try {                // Listen on a specific network interface if it has been set.                String interfaceName = JiveGlobals.getXMLProperty("network.interface");                InetAddress bindInterface = null;                if (interfaceName != null) {                    if (interfaceName.trim().length() > 0) {                        bindInterface = InetAddress.getByName(interfaceName);                    }                }                // Start accepting connections                socketAcceptor                        .bind(new InetSocketAddress(bindInterface, port), new ClientConnectionHandler(serverName));                ports.add(new ServerPort(port, serverName, localIPAddress, false, null, ServerPort.Type.client));                List<String> params = new ArrayList<String>();                params.add(Integer.toString(port));                Log.info(LocaleUtils.getLocalizedString("startup.plain", params));            }            catch (Exception e) {                System.err.println("Error starting XMPP listener on port " + port + ": " +                        e.getMessage());                Log.error(LocaleUtils.getLocalizedString("admin.error.socket-setup"), e);            }        }    }
其中的socketAcceptor.bind()方法啟動了監聽伺服器,來監聽所有發送到伺服器5222連接埠的資料,並用ClientConnetionHandler類來處理,ClinetConnectionHandler繼承於ConnectionHandler類,後者實現了mina的IoHandlerAdaptor介面,其中的messageReceived()方法是關鍵。
        public void messageReceived(IoSession session, Object message) throws Exception {        // Get the stanza handler for this session        StanzaHandler handler = (StanzaHandler) session.getAttribute(HANDLER);        // Get the parser to use to process stanza. For optimization there is going        // to be a parser for each running thread. Each Filter will be executed        // by the Executor placed as the first Filter. So we can have a parser associated        // to each Thread        int hashCode = Thread.currentThread().hashCode();        XMPPPacketReader parser = parsers.get(hashCode);        if (parser == null) {            parser = new XMPPPacketReader();            parser.setXPPFactory(factory);            parsers.put(hashCode, parser);        }        // Update counter of read btyes        updateReadBytesCounter(session);        //System.out.println("RCVD: " + message);        // Let the stanza handler process the received stanza        try {            handler.process((String) message, parser);        } catch (Exception e) {            Log.error("Closing connection due to error while processing message: " + message, e);            Connection connection = (Connection) session.getAttribute(CONNECTION);            connection.close();        }    }
可以看到收到的資訊交由StanzaHandler的process方法中進行XML解析並封裝為packet對象,然後再進行下一步的處理,至此,從用戶端到伺服器端的packet傳遞結束。


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.