最近准备开发即时通讯的业务,今天搭建了一下开发的环境服务器软件选择openfire

看了下类似的软件有ejabberd(erlang开发) 和 djabberd(memcached的作者写的perl开发)因为对这两种语言都不太熟悉,所以选择了openfire,大概看下来openfire结构还是很清晰的,很容易上手

openfire的部署这里就不再赘述参考:http://wenku.baidu.com/view/c87d385f312b3169a451a4ae.html

回想我们平时用qq聊天的过程是怎么样的。a向b发送消息 b的客户端就会有消息提示 但a如果是多个客户段同时登陆服务器是怎么处理的。

这些问题要通过xmpp协议解决

看一个xmpp的message报文

<message id="OBM1n-13" to="b@domain" from="a@domain/res" type="chat">
  <body>Hello</body>
  <thread>0h6GG0</thread>
</message>

属性tofrom就是用户的id,由三部分组成username @ domain / resourceusername就是用户名 domain就是用户注册帐号所在服务器名 resource就是当前登陆的客户端识别id

xmpp协议中同一帐号同时在不同的客户端登陆靠的就是resource字段,resource字段是可选的。

再接着看mssage报文 to中没有resource 服务器根据当前的配置选择发送消息给最佳的客户端或发送给全部的b所登陆的客户端

服务器的配置可以在admin界面设置route.all-resourcestrue

相对应的route算法的代码位于RoutingTablerouteToBareJID(2)

private boolean routeToBareJID(JID recipientJID, Message packet) {
    List<ClientSession> sessions = new ArrayList<ClientSession>();
    // Get existing AVAILABLE sessions of this user or AVAILABLE to the sender of the packet
    for (JID address : getRoutes(recipientJID, packet.getFrom())) {
        ClientSession session = getClientRoute(address);
        if (session != null) {
            sessions.add(session);
        }
    }
    //getHighestPrioritySessions这个函数可以对不同优先级的客户端做排序及筛选处理
    sessions = getHighestPrioritySessions(sessions);
    if (sessions.isEmpty()) {
        // No session is available so store offline
	Log.debug("Unable to route packet. No session is available so store offline. {} ", packet.toXML());
        return false;
    }
    else if (sessions.size() == 1) {
        // Found only one session so deliver message
        sessions.get(0).process(packet);
    }
    else {
        // Many sessions have the highest priority (be smart now) :)
        if (!JiveGlobals.getBooleanProperty("route.all-resources", false)) {
            //此处代码用于选择一个最佳客户端发送 我们的需求是全部都要发送故不列出
	    ...
        }
        else {
            // Deliver stanza to all connected resources with highest priority
            for (ClientSession session : sessions) {
                session.process(packet);
            }
        }
    }
    return true;
}

不同的domain的用户的route不在这里处理 不过现在的xmpp服务器大多都不喜欢和别的xmpp通讯 比如gtalk,msn,qq都不能相互通讯那个功能貌似都已经废了。顺带一题openfire的源码真的不错,注释风格是从伪码过来的,不是后期补注释硬加上去的,改起来也很方便。