XMPP大雜燴

XMPP大雜燴

對XMPP的理解

XMPP是基於XML的即時通信協議。對即時通信場景進行了高度抽象,好比用訂閱對方的上下線狀態表示好友。提供了文本通信、用戶上下線通知、聯繫人管理、羣組聊天等功能,還能夠安裝插件或自行拓展。java

服務端的安裝

服務端通常用OpenFire。git

以macOS爲例,官網直接下載安裝包,安裝完成後,在系統菜單中打開OpenFire控制檯,進入OpenFire的Web後臺,走完配置嚮導。數據庫能夠用OpenFire自帶的嵌入式數據庫,也能夠配置爲MySQL。若是是局域網測試的話,主機名最好設置成內網IP。最後一步須要設置管理員密碼,管理員的帳號是admin。配置完成後,能夠登陸OpenFire的管理後臺。github

OpenFire服務器默認開放用戶註冊、開放建羣,因此能夠無論OpenFire後臺,直接拿來使用。數據庫

用戶註冊

大多XMPP客戶端不提供用戶註冊功能,因此最好在OpenFire後臺直接添加用戶。試了多個客戶端,只有Psi能夠成功註冊用戶,並且登陸以後找不到退出的地方,也找不到建立用戶的地方。安全

客戶端的選擇

XMPP的圖形客戶端特別多,可是一個比一個難用。在macOS上勉強可使用的主要有Spark、Adium和Thunderbird。Spark是OpenFire官方提供的客戶端,在使用時要注意禁用安全選項,若是主機不受信任的話。服務器

命令行下的客戶端,可使用Profanitytcp

用戶登陸

登陸XMPP帳戶,須要服務器、用戶名、密碼三個字段。若是客戶端沒有提供單獨的服務器輸入框的話,用戶名改用用戶名@服務器測試

Profanity的使用

Profanity不提供用戶註冊功能,須要先在後臺添加用戶,或者用其餘客戶端註冊。ui

  • 登陸 /connect 用戶名@服務器 tls disable
  • 登出 /disconnect
  • 開啓聊天 /msg 用戶名@服務器/用戶暱稱 文本
  • 切換窗口 Alt/Option+數字 Alt+1是系統窗口,其餘是聊天窗口
  • 添加用戶到通信錄(非好友,不能訂閱用戶的上下線消息) /roster add 用戶名@服務器
  • 添加用戶爲好友 /sub request 用戶名@服務器
  • 收到添加好友請求時容許 /sub allow 用戶名@服務器
  • 進入聊天室/羣組/房間,不存在則根據嚮導建立 /join 房間名@服務器
  • 切換在線狀態 /away=離開 /online=在線 /dnd=忙碌 ...
  • 退出軟件 /quit

Smack的使用

Smack是OpenFire提供的支持XMPP協議的Java接口.net

引入Smack依賴

  • org.igniterealtime.smack:smack-tcp 同時包含了Smack核心庫。之因此有這個包,是由於XMPP也能運行在其餘協議之上
  • org.igniterealtime.smack:smack-java7 平臺依賴。用做初始化。不包含此庫也能編譯成功,可是跑不起來
  • org.igniterealtime.smack:smack-extensions Smake擴展包。算是必備,至少聯繫人管理功能須要這個包

Smack示例代碼

package bj;

import io.vavr.control.Try;
import lombok.extern.slf4j.Slf4j;
import org.jivesoftware.smack.AbstractXMPPConnection;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.chat2.ChatManager;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.roster.Roster;
import org.jivesoftware.smack.roster.RosterEntry;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
import org.junit.Test;
import org.jxmpp.jid.impl.JidCreate;

import java.io.IOException;
import java.net.InetAddress;
import java.util.Set;

/**
 * Created by BaiJiFeiLong@gmail.com at 2018/11/22 下午4:33
 */
@Slf4j
public class BazTest {

    @Test
    public void testAlpha() throws IOException, InterruptedException, XMPPException, SmackException {
        // 建立鏈接,並鏈接到服務器
        AbstractXMPPConnection connection = new XMPPTCPConnection(XMPPTCPConnectionConfiguration.builder()
                .setUsernameAndPassword("gamma", "gamma")
                .setXmppDomain("172.16.5.254")
                .setHostAddress(InetAddress.getByName("172.16.5.254")) // 服務器地址直接用IP的話,不能用setHost()
                .setSecurityMode(ConnectionConfiguration.SecurityMode.disabled) // 禁用安全模式,若是服務器不受信任
                .build()).connect();
        connection.login();

        // 監聽XMPP包(包括PING、在線狀態、聊天消息等)
        connection.addSyncStanzaListener(packet -> log.info("[SyncStanzaListener] Packet received {}", packet), stanza -> true);

        // 只監聽聊天消息
        ChatManager.getInstanceFor(connection).addIncomingListener((entityBareJid, message, chat) -> {
            System.out.println(String.format("[IncomingListener] Message received %s : %s", entityBareJid, message.getBody()));
            // Echo此消息
            Try.run(() -> chat.send(message.getBody()));
            System.out.println(Roster.getInstanceFor(connection).getEntries());
        });

        // 發送消息
        connection.sendStanza(new Message("theta@172.16.5.254", "MESSAGE_BY_CONNECTION"));
        // 發送消息 方式二
        ChatManager.getInstanceFor(connection).chatWith(JidCreate.entityBareFrom("theta@172.16.5.254")).send("MESSAGE_BY_CHAT_MANAGER");

        // 獲取聯繫人集合
        Thread.sleep(1000); // 等待聯繫人更新
        Set<RosterEntry> entries = Roster.getInstanceFor(connection).getEntries();
        log.info("Contacts: {} persons", entries.size());
        entries.forEach(System.out::println);

        // 保持運行
        Thread.currentThread().join();
    }
}

控制檯日誌

10:55:24.924 [Smack Cached Executor] INFO bj.BazTest - [SyncStanzaListener] Packet received IQ Stanza (query jabber:iq:roster) [to=gamma@172.16.5.254/612m1g1ciz,id=gvsBl-5,type=result,]
10:55:24.933 [Smack Cached Executor] INFO bj.BazTest - [SyncStanzaListener] Packet received Presence Stanza [to=gamma@172.16.5.254/612m1g1ciz,from=gamma@172.16.5.254/1gwvh0rdvv,id=L85kQ-6,type=available,]
10:55:24.933 [Smack Cached Executor] INFO bj.BazTest - [SyncStanzaListener] Packet received Presence Stanza [to=gamma@172.16.5.254/612m1g1ciz,from=gamma@172.16.5.254/1pj92olp11,id=RamcN-7,type=available,]
10:55:24.933 [Smack Cached Executor] INFO bj.BazTest - [SyncStanzaListener] Packet received Presence Stanza [to=gamma@172.16.5.254/612m1g1ciz,from=gamma@172.16.5.254/8aadbwm30s,id=xkaYN-7,type=available,]
10:55:24.934 [Smack Cached Executor] INFO bj.BazTest - [SyncStanzaListener] Packet received Presence Stanza [to=gamma@172.16.5.254/612m1g1ciz,from=gamma@172.16.5.254/profanity,id=prof_presence_595,type=available,]
10:55:24.937 [Smack Cached Executor] INFO bj.BazTest - [SyncStanzaListener] Packet received Presence Stanza [to=gamma@172.16.5.254/612m1g1ciz,from=gamma@172.16.5.254/9trigmn7f2,id=SJ41s-7,type=available,]
10:55:24.937 [Smack Cached Executor] INFO bj.BazTest - [SyncStanzaListener] Packet received Presence Stanza [to=gamma@172.16.5.254/612m1g1ciz,from=gamma@172.16.5.254/42awvmq6te,id=iMJUx-6,type=available,]
10:55:24.937 [Smack Cached Executor] INFO bj.BazTest - [SyncStanzaListener] Packet received Presence Stanza [to=gamma@172.16.5.254/612m1g1ciz,from=gamma@172.16.5.254/92ijqtzgxi,id=9gG6o-7,type=available,]
10:55:24.937 [Smack Cached Executor] INFO bj.BazTest - [SyncStanzaListener] Packet received Presence Stanza [to=gamma@172.16.5.254/612m1g1ciz,from=gamma@172.16.5.254/494vwn454w,id=byYRm-7,type=available,]
10:55:24.938 [Smack Cached Executor] INFO bj.BazTest - [SyncStanzaListener] Packet received Presence Stanza [to=gamma@172.16.5.254/612m1g1ciz,from=gamma@172.16.5.254/4wurqkoj8y,id=3BnGN-7,type=available,]
10:55:24.939 [Smack Cached Executor] INFO bj.BazTest - [SyncStanzaListener] Packet received Presence Stanza [to=gamma@172.16.5.254/612m1g1ciz,from=gamma@172.16.5.254/9vx8ve5vdm,id=YSZxk-6,type=available,]
10:55:25.939 [main] INFO bj.BazTest - Contacts: 3 persons
: beta@172.16.5.254
: alpha@172.16.5.254
: theta@172.16.5.254
10:55:26.876 [Smack Cached Executor] INFO bj.BazTest - [SyncStanzaListener] Packet received Message Stanza [to=gamma@172.16.5.254/612m1g1ciz,from=theta@172.16.5.254/profanity,id=prof_msg_670,type=chat,]
[IncomingListener] Message received theta@172.16.5.254 : hello
[: beta@172.16.5.254, : alpha@172.16.5.254, : theta@172.16.5.254]
10:55:28.839 [Smack Cached Executor] INFO bj.BazTest - [SyncStanzaListener] Packet received Message Stanza [to=gamma@172.16.5.254/612m1g1ciz,from=theta@172.16.5.254/profanity,id=prof_msg_671,type=chat,]
[IncomingListener] Message received theta@172.16.5.254 : world
[: beta@172.16.5.254, : alpha@172.16.5.254, : theta@172.16.5.254]

文章首發https://baijifeilong.github.io/2018/11/22/xmpp

相關文章
相關標籤/搜索