1. 程式人生 > >Openfire即時通訊服務搭建與Smack訪問

Openfire即時通訊服務搭建與Smack訪問

Openfire 是開源的、基於可拓展通訊和表示協議(XMPP)、採用Java程式語言開發的實時協作伺服器。 Openfire安裝和使用都非常簡單,並利用Web進行管理。單臺伺服器可支援上萬併發使用者。

首先到openfire官網上去下載Openfire的伺服器包與Smack的客戶端呼叫包。

開啟後在這裡可以看到有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();
		}
	}

執行後可以分別在這兩個控制檯上看到收到的訊息



看到這裡,說明已經可以正常通訊,收發訊息了。