zoukankan      html  css  js  c++  java
  • openfire和mina(一)转

    openfire和mina(一)

    1815人阅读 评论(3) 收藏 举报

          看了几天的openfire,网上的资料太少了,只有一个国外的网站不错,http://www.igniterealtime.org/ ,其他的只能自己摸索了。

    openfire启动:

    ServerStarter

    会加载 org.jivesoftware.openfire.XMPPServer

    在XMPPServer会加载一系列模块

    其中的ConnectionManagerImpl 是连接模块

     // Load this module always last since we don't want to start listening for clients
            // before the rest of the modules have been started
            loadModule(ConnectionManagerImpl.class.getName());

    ConnectionManagerImpl 会启动一系列的监听。

    其中的createClientListeners和startClientListeners是我比较关心的,先看看再这里面openfire都做了什么!

    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());
            }
        }

    对了这里就是和用的mian框架去做联网处理,首先设置mina框架的线程池,然后把由XMPPCodecFactory做为ProtocolCodecFilter的chain添加到FilterChain中!

    然后

    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(new InetSocketAddress(bindInterface, port), new ClientConnectionHandler(serverName));

    ClientConnectionHandler作为数据处理

    服务器去监听5222端口去了,mina真方便!

     关于MINA框架可以去网上找找资料,这里就不说了。

      这里要说下MINA中的IoHandler这个接口,IoHandler是最终面对用户的接口,看下这个接口中的方法:


    public interface IoHandler {
        /**
         * Invoked from an I/O processor thread when a new connection has been created.
         * Because this method is supposed to be called from the same thread that
         * handles I/O of multiple sessions, please implement this method to perform
         * tasks that consumes minimal amount of time such as socket parameter
         * and user-defined session attribute initialization.
         */

        void sessionCreated(IoSession session) throws Exception;

        /**
         * Invoked when a connection has been opened.  This method is invoked after
         * {@link #sessionCreated(IoSession)}.  The biggest difference from
         * {@link #sessionCreated(IoSession)} is that it's invoked from other thread
         * than an I/O processor thread once thread model is configured properly.
         */

        void sessionOpened(IoSession session) throws Exception;

        /**
         * Invoked when a connection is closed.
         */

        void sessionClosed(IoSession session) throws Exception;

        /**
         * Invoked with the related {@link IdleStatus} when a connection becomes idle.
         * This method is not invoked if the transport type is UDP; it's a known bug,
         * and will be fixed in 2.0.
         */

        void sessionIdle(IoSession session, IdleStatus status) throws Exception;

        /**
         * Invoked when any exception is thrown by user {@link IoHandler}
         * implementation or by MINA.  If <code>cause</code> is an instance of
         * {@link IOException}, MINA will close the connection automatically.
         */

        void exceptionCaught(IoSession session, Throwable cause) throws Exception;

        /**
         * Invoked when a message is received.
         */

        void messageReceived(IoSession session, Object message) throws Exception;

        /**
         * Invoked when a message written by {@link IoSession#write(Object)} is
         * sent out.
         */

        void messageSent(IoSession session, Object message) throws Exception;
    }


    在mina中实现这个接口的类是IoHandlerAdapter 这个类

    /**
     * An abstract adapter class for {@link IoHandler}.  You can extend this
     * class and selectively override required event handler methods only.  All
     * methods do nothing by default.
     *
     * @author The Apache MINA Project (dev@mina.apache.org)
     * @version $Rev: 671827 $, $Date: 2008-06-26 10:49:48 +0200 (jeu, 26 jun 2008) $
     */

    public class IoHandlerAdapter implements IoHandler {

        private final Logger logger = LoggerFactory.getLogger(getClass());

        public void sessionCreated(IoSession session) throws Exception {
        }

        public void sessionOpened(IoSession session) throws Exception {
        }

        public void sessionClosed(IoSession session) throws Exception {
        }

        public void sessionIdle(IoSession session, IdleStatus status)
                throws Exception {
        }

        public void exceptionCaught(IoSession session, Throwable cause)
                throws Exception {
            if (logger.isWarnEnabled()) {
                logger.warn("EXCEPTION, please implement "
                        + getClass().getName()
                        + ".exceptionCaught() for proper handling:", cause);
            }
        }

        public void messageReceived(IoSession session, Object message)
                throws Exception {
        }

        public void messageSent(IoSession session, Object message) throws Exception {
        }
    }


    接下来转到openfire,在openfire中ConnectionHandler类继承自IoHandlerAdapter,也就充当着最后要面对用户的角色。

    public abstract class ConnectionHandler extends IoHandlerAdapter

          这个是ConnectionHandler的类图,可以看出他有3个子类,而其中的ClientConnectionHandler是处理客户端和服务器连接用到的,也是我先要说明的。


         当有客户端进行连接的时候MINA框架会调用IoHandler的sessionOpened(),

        public void sessionOpened(IoSession session) throws Exception {
            // Create a new XML parser for the new connection. The parser will be used by the XMPPDecoder filter.
            XMLLightweightParser parser = new XMLLightweightParser(CHARSET );
            session.setAttribute(XML_PARSER, parser);
            // Create a new NIOConnection for the new session
            NIOConnection connection = createNIOConnection(session);
            session.setAttribute(CONNECTION , connection);
            session.setAttribute(HANDLER , createStanzaHandler(connection));
            // Set the max time a connection can be idle before closing it
            int idleTime = getMaxIdleTime();
            if (idleTime > 0) {
                session.setIdleTime(IdleStatus.READER _IDLE, idleTime);
            }
        }
    可以看到这里分别创建了XMLLightweightParser,NIOConnection,ClientStanzaHandler实例并将它们放到了session中


          当客户端往服务器发送消息的时候会调用IoHandler的messageReceived(IoSession session, Object message)

        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();
            }
        }
    在这里得到了XMPPPacketReader 然后处理过来的XML数据。

    到这里就完成了C------>S的数据传输,数据通过MINA层来到了XMPP层

  • 相关阅读:
    01 变量、基本数据类型
    02 gitlab的基本使用
    kubernetes
    02 redis高可用集群
    Redis & ELK
    01 Redis安装、配置详解、数据备份与恢复
    Jenkins
    01 git gitlab jenkins的安装
    golang mysql 客户端
    接口类
  • 原文地址:https://www.cnblogs.com/avenxia/p/2316273.html
Copyright © 2011-2022 走看看