首页 > 代码库 > Openfire即时通讯服务搭建与Smack访问

Openfire即时通讯服务搭建与Smack访问

Openfire 是开源的、基于可拓展通讯和表示协议(XMPP)、采用Java编程语言开发的实时协作服务器。 Openfire安装和使用都非常简单,并利用Web进行管理。单台服务器可支持上万并发用户。

首先到openfire官网上去下载Openfire的服务器包与Smack的客户端调用包。

http://www.igniterealtime.org/projects/index.jsp

技术分享

打开后在这里可以看到有Openfire,Spark,Smack这三个东西,我简单解释一下它们分别是什么,Openfire是跑在服务器的,Spark与Smack是跑在客户机上的,而Spark是已经构建好的应用程序,下载下来安装即可使用(看下面的截图),Smack是提供访问Openfire的调用接口,就是做开发写代码的啦。

技术分享技术分享


Openfire下载后,如果是win的版本,那么它是一个exe的安装包,运行下一步下一步即可,其间会需要配置数据库(Openfire当然是需要数据库支持的了,比如要存帐号等等的信息)。具体可以参照这个 http://jingyan.baidu.com/article/2c8c281df16ad30008252ae4.html


Openfire安装成功后,下载Smack的包,里边包含有相应接口的jar包,导入到我们的工程里(不同版本的smack jar可能会不太一样)

技术分享技术分享


编写我们的程序访问Operfire

import java.util.Collection;
import java.util.Iterator;

import javax.net.SocketFactory;

import org.jivesoftware.smack.AccountManager;
import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.ChatManager;
import org.jivesoftware.smack.ChatManagerListener;
import org.jivesoftware.smack.Connection;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.MessageListener;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.Session;
import org.jivesoftware.smack.packet.Message.Type;

public class SmackUtil {
 
    private Connection connection;
    private ConnectionConfiguration config;
    /** openfire服务器address */
    private final static String server = "10.100.53.65";
    
    private final void print(Object o) {
        if (o != null) {
            System.out.println(o);
        }
    }
    
    private final void print(Object o, Object... args) {
        if (o != null && args != null && args.length > 0) {
            String s = o.toString();
            for (int i = 0; i < args.length; i++) {
                String item = args[i] == null ? "" : args[i].toString();
                if (s.contains("{" + i + "}")) {
                    s = s.replace("{" + i + "}", item);
                } else {
                    s += " " + item;
                }
            }
            System.out.println(s);
        }
    }
    
    /**
     * 初始Smack对openfire服务器链接的基本配置
     */
    public void init() {
        try {
            //connection = new XMPPConnection(server);
            //connection.connect();
            /** 5222是openfire服务器默认的通信端口,你可以登录http://10.100.53.65:9090/到管理员控制台查看客户端到服务器端口 */
            config = new ConnectionConfiguration(server, 5222);
            
            /** 是否启用压缩 */ 
            config.setCompressionEnabled(true);
            /** 是否启用安全验证 */
            config.setSASLAuthenticationEnabled(true);
            /** 是否启用调试 */
            config.setDebuggerEnabled(false);
            config.setReconnectionAllowed(true);
            config.setRosterLoadedAtLogin(true);
            
            /** 创建connection链接 */
            connection = new XMPPConnection(config);
            /** 建立连接 */
            connection.connect();
            System.out.println("connection success");
        } catch (XMPPException e) {
            e.printStackTrace();
        }
        print(connection);
        print(connection.getConnectionID());
    }
    
    public void destory() {
        if (connection != null) {
            connection.disconnect();
            connection = null;
        }
    }
    
    /**
     * ConnectionConfiguration 的基本配置相关信息
     */
    public void seeConfig() {
        print("PKCS11Library: " + config.getPKCS11Library());
        print("ServiceName: {0}", config.getServiceName());
        // ssl证书密码
        print("TruststorePassword: {0}", config.getTruststorePassword());
        print("TruststorePath: {0}", config.getTruststorePath());
        print("TruststoreType: {0}", config.getTruststoreType());
        
        SocketFactory socketFactory = config.getSocketFactory();
        print("SocketFactory: {0}", socketFactory);
    }
    
    /**
     * Connection 基本方法信息
     */
    public void seeConnection() {
        /** 用户管理 */
        AccountManager accountManager = connection.getAccountManager();
        for (String attr : accountManager.getAccountAttributes()) {
            print("AccountAttribute: {0}", attr);
        }
        print("AccountInstructions: {0}", accountManager.getAccountInstructions());
        /** 是否链接 */
        print("isConnected:", connection.isConnected());
        print("isAnonymous:", connection.isAnonymous());
        /** 是否有权限 */
        print("isAuthenticated:", connection.isAuthenticated());
        print("isSecureConnection:", connection.isSecureConnection());
        /** 是否使用压缩 */
        print("isUsingCompression:", connection.isUsingCompression());
    }
    
    /**
     * 创建用户
     * @param username
     * @param password
     */
    public void createUser(String username, String password){
    	AccountManager accountManager = connection.getAccountManager();
    	try {
    		/** 创建一个用户;你可以在管理员控制台页面http://10.100.53.65:9090/user-summary.jsp查看用户/组的相关信息,来查看是否成功创建用户 */
    		accountManager.createAccount(username, password);
    		/** 修改密码 */
    		accountManager.changePassword("abc");
    	} catch (XMPPException e) {
    		e.printStackTrace();
    	}    	
    }
    
    /**
     * 修改密码
     * @param username
     * @param password
     */
    public void changePassword(String password){
    	AccountManager accountManager = connection.getAccountManager();
    	try {
    		/** 修改密码 */
    		accountManager.changePassword("123456");
    	} catch (XMPPException e) {
    		e.printStackTrace();
    	}    	
    }
    
    
    /**
     * 用户登陆
     * @param username
     * @param password
     */
    public void login(String username, String password) {
        try {
            /** 用户登陆,用户名、密码 */
            connection.login(username, password);
        } catch (XMPPException e) {
            e.printStackTrace();
        }
        /** 获取当前登陆用户 */
        print("User:", connection.getUser());
        
        /** 所有用户组 */
        Roster roster = connection.getRoster();
        
       /* try {
			roster.createEntry("test55", "test55", null);//添加好友,不添加成为好友也同样可以收发信息
		} catch (XMPPException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}*/
        
        /** 好友用户组,你可以用Spark添加用户好友,这样这里就可以查询到相关的数据 */
        Collection<RosterEntry> rosterEntiry = roster.getEntries();
        Iterator<RosterEntry> iter = rosterEntiry.iterator();
        while (iter.hasNext()) {
            RosterEntry entry = iter.next();
            print("Groups: {0}, Name: {1}, Status: {2}, Type: {3}, User: {4}", entry.getGroups(), entry.getName(), entry.getStatus(), entry.getType(), entry);
        }
        
        print("-------------------------------");
        /** 未处理、验证好友,添加过的好友,没有得到对方同意 */
        Collection<RosterEntry> unfiledEntries = roster.getUnfiledEntries();
        iter = unfiledEntries.iterator();
        while (iter.hasNext()) {
            RosterEntry entry = iter.next();
            print("Groups: {0}, Name: {1}, Status: {2}, Type: {3}, User: {4}", entry.getGroups(), entry.getName(), entry.getStatus(), entry.getType(), entry);
        }        
    }
    
    /**
     * 添加消息监听器
     */
    public void addMsgListener(){
    	//监听接收到的消息
    	connection.getChatManager().addChatListener(new ChatManagerListener() {	//可以监听到所有用户发来的消息		
    		@Override
    		public void chatCreated(Chat chat, boolean createdLocally) {
    			chat.addMessageListener(new MessageListener() {  
    				public void processMessage(Chat chat, Message message) {  
    					//String from = message.getFrom();  
    					//String body =  message.getBody();  
    					System.out.println("body:"+message.getBody());
    					
    				}  
    			});  				
    		}
    	});    	
    }
    
    /**
     * Packet消息聊天
     * @param from
     * @param to
     * @param msg
     */
    public void sendPacketMsg(String from, String to, String msg) {
//        try {
//            connection.login(from, from);
//        } catch (XMPPException e) {
//            e.printStackTrace();
//        }
        
        /** 更改用户状态,available=true表示在线,false表示离线,status状态签名;当你登陆后,在Spark客户端软件中就可以看到你登陆的状态 */
        Presence presence = new Presence(Presence.Type.available);
        presence.setStatus("Q我吧");
        connection.sendPacket(presence);
        
        Session session = new Session();
        //String sessid = session.nextID();
        connection.sendPacket(session);
        Message message = new Message(to+"@" + server, Type.chat);
        //Message message = new Message(sessid, Type.chat);
        message.setBody(msg);
        connection.sendPacket(message);
    }
    
    /**
     * Chat消息聊天
     * @param from
     * @param to
     * @param msg
     */
    public void sendChatMsg(String from, String to, String msg) {
        /** 设置状态 */
//        try {
//            connection.login(from, from);
//        } catch (XMPPException e) {
//            e.printStackTrace();
//        }
        
        /** 设置状态 */
        Presence presence = new Presence(Presence.Type.available);
        presence.setStatus("Q我吧");
        connection.sendPacket(presence);
        
        /** 获取当前登陆用户的聊天管理器 */
        ChatManager chatManager = connection.getChatManager();
        /** 为指定用户创建一个chat,监听对方发过来的消息  */
        Chat chat = chatManager.createChat(to+"@" + server, new MessageListener() {//仅监听该用户发来的消息
			
			@Override
			public void processMessage(Chat chat, Message message) {
				System.out.println("body:"+message.getBody());				
			}
		});
        try {
            /** 发送消息 */
            chat.sendMessage(msg);
            
            /** 用message对象发送消息 */
//            Message message = new Message();
//            message.setBody("message");
//            message.setProperty("color", "red");
//            chat.sendMessage(message);
        } catch (XMPPException e) {
            e.printStackTrace();
        }
    }
    
}

创建两个通讯的测试帐号

public static void main(String[] args) {
		SmackUtil smackUtil = new SmackUtil();
		
		smackUtil.init();
		smackUtil.seeConfig();
		smackUtil.seeConnection();
		
		smackUtil.createUser("test1", "test1");	
		
	}

public static void main(String[] args) {
		SmackUtil smackUtil = new SmackUtil();
		
		smackUtil.init();
		smackUtil.seeConfig();
		smackUtil.seeConnection();
		
		smackUtil.createUser("test2", "test2");	
		
	}

利用刚创建好的帐号来登陆并发送消息

test1 登陆并发送消息:

public static void main(String[] args) {
		SmackUtil smackUtil = new SmackUtil();
		
		smackUtil.init();
		smackUtil.seeConfig();
		smackUtil.seeConnection();
		
		smackUtil.login("test1", "test1");
		smackUtil.addMsgListener();
		smackUtil.sendChatMsg("test1","test2","1111111111111111111111111111111111111");
		smackUtil.sendPacketMsg("test1","test2","1111111111111111111111111111111111111");
		
		
		try {
			Thread.sleep(1000*1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

test2 登陆并发送消息:

public static void main(String[] args) {
		SmackUtil smackUtil = new SmackUtil();
		
		smackUtil.init();
		smackUtil.seeConfig();
		smackUtil.seeConnection();
		
		smackUtil.login("test2", "test2");
		smackUtil.addMsgListener();		
		
		smackUtil.sendChatMsg("test2","test1","222222222222222222222222222222222222222");
		smackUtil.sendPacketMsg("test2","test1","222222222222222222222222222222222222222");
		
		try {
			Thread.sleep(100*1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

运行后可以分别在这两个控制台上看到收到的消息

技术分享技术分享

技术分享技术分享

看到这里,说明已经可以正常通讯,收发消息了。


Openfire即时通讯服务搭建与Smack访问