Jive Messenger 源码研究

  Jive Messenger 源码研究
第一部分 Jabber Server工作原理和流程
1)Server的启动
通过下面图片来做一个简单的了解
 
1.       Launcher(GUI) Jive Messenger Server 启动和停止的可视化界面 ,
按下 Start Server 开始启动
:[org.jivesoftware.messenger.launcher.Launcher] 调用 ServerStarter.start()
2.       [org.jivesoftware.messenger.starter.ServerStarter] 加载 lib 库文件 , 同时启动一个
[org.jivesoftware.messenger.XMPPServer] 实体

Class containerClass = loader.loadClass("org.jivesoftware.messenger.XMPPServer");
containerClass.newInstance();
 
3.       XMPPServer 加载模块 (Modules), 组件 (Component), 插件 (Plugin)

public void start() {
        try {
            initialize();
 
            // If the server has already been setup then we can start all the server's modules
            if (!setupMode) {
                verifyDataSource();
                // First load all the modules so that modules may access other modules while
                // being initialized
                loadModules() ;
                // Initize all the modules
                initModules();
                // Start all the modules
                startModules();
            }
           // Load plugins. First, initialize component manager.
            InternalComponentManager.getInstance().start();
            File pluginDir = new File(messengerHome, "plugins");
            pluginManager = new PluginManager(pluginDir);
            pluginManager.start();
            …….
        }
        catch (Exception e) {
            …..
            shutdownServer();
        }
    }
 
下面我们来看一下服务器加载了那些 Module(Component,Plugin 也是非常重要的我将在以后的文章中做讨论 )

private void loadModules() {
        // Load boot modules
        loadModule(RoutingTableImpl.class.getName());
        loadModule(AuditManagerImpl.class.getName());
        loadModule(RosterManager.class.getName());
        loadModule(PrivateStorage.class.getName());
        // Load core modules
        loadModule(PresenceManagerImpl.class.getName());
        loadModule(SessionManager.class.getName());
        loadModule(PacketRouter.class.getName());
        loadModule(IQRouter.class.getName());
        loadModule(MessageRouter.class.getName());
        loadModule(PresenceRouter.class.getName());
        loadModule(PacketTransporterImpl.class.getName());
        loadModule(PacketDelivererImpl.class.getName());
        loadModule(TransportHandler.class.getName());
        loadModule(OfflineMessageStrategy.class.getName());
        loadModule(OfflineMessageStore.class.getName());
        // Load standard modules
        loadModule(IQAuthHandler.class.getName());
        loadModule(IQPrivateHandler.class.getName());
        loadModule(IQRegisterHandler.class.getName());
        loadModule(IQRosterHandler.class.getName());
        loadModule(IQTimeHandler.class.getName());
        loadModule(IQvCardHandler.class.getName());
        loadModule(IQVersionHandler.class.getName());
        loadModule(IQLastActivityHandler.class.getName());
        loadModule(PresenceSubscribeHandler.class.getName());
        loadModule(PresenceUpdateHandler.class.getName());
        loadModule(IQDiscoInfoHandler.class.getName());
        loadModule(IQDiscoItemsHandler.class.getName());
        loadModule(IQOfflineMessagesHandler.class.getName());
        loadModule(MultiUserChatServerImpl.class.getName());
        loadModule(MulticastDNSService.class.getName());
        // 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());
    }
Server 启动的时候加载的模块非常多 , 其中最后一个加载的 ConnectionManagerImpl 它是 ConnectionManager 接口的实现 , 用来负责管理用户 (jabberClient) 连接
 
另外所有模块都是继承 (extends) BasicModule 或者实现 (implements) Module
4. ConnectionManageImpl 启动

 public void start() {
        super.start();
        isStarted = true;
        serverName = server.getServerInfo().getName();
        createSocket();
        SocketSendingTracker.getInstance().start();
    }
Start 方法创建 Socket( 监听客户端的连接 ), 并启动一个 SocketSendingTracker 线程 , 用来检查 Socket 是否正常连接
5.JabberServer 启动完成
2) 客户端连接 , 待续
 
2 Client Server 交互流程

1   客户端启动一个 XMPPConnection Server 建立 Socket 的连接
2   用户通过 PacketWriter IQ Server ,服务器 ClientSocketReader 接受到这个 IQ ,对用户登陆进行认证
3   ClientA Packet ClientB ClientSocketReader 会调用 PacketRouter Packet 转发给 ClientB (现在先不太 Server2Server 的情况)
Jive Messenger Server 如何创建 Session (代码分析)
 
 
ConnectionManagerImpl 初始化(

//ConnectionManagerImpl.java
public void initialize(XMPPServer server) {
        super.initialize(server);
        this.server = server;
        router = server.getPacketRouter();
        deliverer = server.getPacketDeliverer();
        sessionManager = server.getSessionManager();
    }
ConnectionManagerImpl 启动

//ConnectionManagerImpl.java
public void start() {
        super.start();
        isStarted = true;
        serverName = server.getServerInfo().getName();
        createSocket();
        SocketSendingTracker.getInstance().start();
    }
ConnectionManagerImpl 创建 Socket

//ConnectionManagerImpl.java
private void createSocket() {
        ……
        // Start the port listener for s2s communication
        startServerListener(localIPAddress);
        // Start the port listener for external components
        startComponentListener(localIPAddress);
        // Start the port listener for clients
        startClientListeners(localIPAddress);
        // Start the port listener for secured clients
        startClientSSLListeners(localIPAddress);
    }
ConnectionManagerImpl 开启 socket 监听,启动 SocketAcceptTread 线程

//ConnectionManagerImpl.java
private void startClientListeners(String localIPAddress) {
            ……
            try {
                socketThread = new SocketAcceptThread (this, serverPort);
                ports.add(serverPort);
                socketThread.setDaemon(true);
                socketThread.start();
                ……
            }
            catch (Exception e) {
               …..
            }
        }
    }
SocketAcceptTread 启动过程

// SocketAcceptTread.java
public void run() {
        while (notTerminated) {
            try {
                Socket sock = serverSocket.accept();
                if (sock != null) {
                    Log.debug("Connect " + sock.toString());
                    connManager.addSocket(sock, false, serverPort);
                }
            }
            catch (IOException ie) {
              …..
                }
                     …..
        }
     // 线程结束的时候后面处理关闭 serverSocket
     ……
    }
当一个 Client 连接到 Server,ConnectionManagerImpl 增加一个 Socket 连接

//ConnectionManagerImpl.java
public void addSocket(Socket sock , boolean isSecure, ServerPort serverPort) {
        try {
            SocketConnection conn = new SocketConnection(deliverer, sock , isSecure);
            SocketReader reader = null;
            String threadName = null;
            if (serverPort.isClientPort()) {
                reader = new ClientSocketReader(router, serverName, sock , conn );
                threadName = "Client SR";
            }
            else if (serverPort.isComponentPort()) {
                reader = new ComponentSocketReader(router, serverName, sock, conn);
                threadName = "Component SR";
            }
            else {
                reader = new ServerSocketReader(router, serverName, sock, conn);
                threadName = "Server SR";
            }
            Thread thread = new Thread(reader, threadName);
             thread.setDaemon(true);
            thread.start();
        }
        catch (IOException e) {
            Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
        }
    }
ConnectionManagerImpl 启动一个 SocketReader 线程

//SocketReader.java
public void run() {
        try {
            reader = new XPPPacketReader();
            reader.setXPPFactory(factory);
            reader.getXPPParser().setInput(new InputStreamReader(socket.getInputStream(),
                    CHARSET));
            // Read in the opening tag and prepare for packet stream
            try {
                //socketReader 启动的时,需要创建一个 Session 来负责和 Client 的会话
                createSession();
            }
            catch (IOException e) {
                …..
            }
            // 会话结束后的处理
            if (session != null) {
                readStream();
            }
 
        }
        catch (EOFException eof) {
            // Normal disconnect
        }
      
    }
createSession() 调用 abstract 方法 createSession(String namespace) ,这个方法的在不同客户端的 SocketReader 中被实现,我们拿 ClientSocketReader 举例

//ClientSocketReader.java
Boolean createSession(String namespace) …{
        if ("jabber:client".equals(namespace)) {
            // ClientSession 负责创建一个 ClientSession
            session = ClientSession.createSession(serverName, reader, connection);
            return true;
        }
        return false;
    }
 ClientSeesion 创建 ClientSeesion 的过程

//ClientSeesion.java
public static Session createSession(String serverName, XPPPacketReader reader,
            SocketConnection connection)
throws XmlPullParserException, UnauthorizedException,IOException{
        ……
        // 为用户创建一个 Session
        Session session = SessionManager.getInstance().createClientSession(connection);
        Writer writer = connection.getWriter();
        // 创建 packet response 的开头
        ……    
        boolean done = false;
        while (!done) {
            if (xpp.next() == XmlPullParser.START_TAG) {
                done = true;
                if (xpp.getName().equals("starttls") &&
                        xpp.getNamespace(xpp.getPrefix()).equals(TLS_NAMESPACE))
                {
                    writer.write("");
                    if (isFlashClient) {
                        writer.write('/0');
                    }
                    writer.flush();
                    // TODO: setup SSLEngine and negotiate TLS.
                }
            }
        }
 
        return session;}
//SessionManager.java
public Session createClientSession(Connection conn) throws UnauthorizedException {
        if (serverName == null) {
            throw new UnauthorizedException("Server not initialized");
        }
        StreamID id = nextStreamID();
        ClientSession session = new ClientSession(serverName, conn, id);
        conn.init(session);
        // Register to receive close notification on this session so we can
        // remove and also send an unavailable presence if it wasn't
        // sent before
        conn.registerCloseListener(clientSessionListener, session);
 
        // Add to pre-authenticated sessions.
        preAuthenticatedSessions.put(session.getAddress().toString(), session);
        return session;
    }
 
总结一下:
1   ConnectionManagermentImpl 初始化启动
2   ConnectionManagermentImpl 创建一个 Socket 启动监听
3   当客户端启动 Socket 连接, SocketAcceptThread 接受客户端连接
ConnectionManagerImpl 调用 addSocket ,创建一个 SocketConnection SocketReader ,并启动 SocketReader 线程
4   SocketReader 会创建一个用户会话( Session

你可能感兴趣的:(技术相关)