XMPP大杂烩

对XMPP的理解

XMPP是基于XML的即时通讯协议。对即时通讯场景进行了高度抽象,比如用订阅对方的上下线状态表示好友。提供了文本通讯、用户上下线通知、联系人管理、群组聊天等功能,还可以安装插件或自行拓展。

服务端的安装

服务端一般用OpenFire。

以macOS为例,官网直接下载安装包,安装完成后,在系统菜单中打开OpenFire控制台,进入OpenFire的Web后台,走完配置向导。数据库可以用OpenFire自带的嵌入式数据库,也可以配置为MySQL。如果是局域网测试的话,主机名最好设置成内网IP。最后一步需要设置管理员密码,管理员的账号是admin。配置完成后,可以登录OpenFire的管理后台。

OpenFire服务器默认开放用户注册、开放建群,所以可以不管OpenFire后台,直接拿来使用。

用户注册

大多XMPP客户端不提供用户注册功能,所以最好在OpenFire后台直接添加用户。试了多个客户端,只有Psi可以成功注册用户,而且登录之后找不到退出的地方,也找不到创建用户的地方。

客户端的选择

XMPP的图形客户端特别多,但是一个比一个难用。在macOS上勉强可以使用的主要有Spark、Adium和Thunderbird。Spark是OpenFire官方提供的客户端,在使用时要注意禁用安全选项,如果主机不受信任的话。

命令行下的客户端,可以使用Profanity

用户登录

登录XMPP账户,需要服务器、用户名、密码三个字段。如果客户端没有提供单独的服务器输入框的话,用户名改用用户名@服务器

Profanity的使用

Profanity不提供用户注册功能,需要先在后台添加用户,或者用其他客户端注册。

  • 登录 /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接口

引入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

XMPP大杂烩的更多相关文章

  1. 技术笔记:XMPP之openfire+spark+smack

    在即时通信这个领域目前只找到一个XMPP协议,在其协议基础上还是有许多成熟的产品,而且是开源的.所以还是想在这个领域多多了解一下. XMPP协议:具体的概念我就不写了,毕竟这东西网上到处是.简单的说就 ...

  2. xmpp

    xmpp学习 下载: Openfire 服务器:Openfire 4.0.2 客户端:Spark 2.7.7 安装 Openfire安装: 根据提示一直下一步,服务器域名设置为:localhost(p ...

  3. iOS XMPP 通信协议实现 图形化直观感受

    第一次随笔,实在不知写点什么有用的东西,那就分享一下本人最近的研究所得吧! 是关于iOS-XMPP-通信协议的实现,具体代码比较复杂,三言两句也实在难表达清楚,网上已有很多关于iOS XMPP协议的讲 ...

  4. (转)C# XMPP客户端与openfire通信(Matrix Xmpp 授权破解教程)

    FROM:http://www.cnblogs.com/crabo/p/CRACK_MATRIX_XMPP.html 如此著名的XMPP , 居然试过jabber-net, agsXmpp,matri ...

  5. XMPP iOS客户端实现三:登录、注册

    1.创建一个单例模式来管理xmpp的连接和操作 +(XMPPManager *)share { static XMPPManager *_share=nil; static dispatch_once ...

  6. XMPP iOS客户端实现二:xcode项目配置

    1.下载XMPPFramework,下载地址:https://github.com/robbiehanson/XMPPFramework 2.创建项目并将XMPP库引入: 3.添加需要的库文件: 4. ...

  7. Openfire/XMPP学习之——一个简单的Smack样例

    昨天讲了Openfire的搭建和配置,今天来讲一下Smack.如果对如何搭建和配置Openfire的,可以参考Openfire/XMPP学习之——Openfire的安装.配置. Smack是一个开源, ...

  8. MAC下的XMPP环境搭建

    实现即时通信有多种方式,下面讲的是Mac下使用XMPP来实现. XML Messages Presence Protocol 可扩展消息处理协议 简单讲就是基于XML语言的点对点即时通信协议  原理: ...

  9. XMPP开发环境配置

    首先配置XMPP开发环境配置需要的软件 先安装xampp-osx-1.8.3-5-installer.dmg 安装成功后launchpad里会多出一个XAMPP(其他),点开里面的manager-os ...

随机推荐

  1. cerr与cout区别

    语言:C++ 一.简介 平常常会用的主要有三个:cout.cerr.clog,首先简单介绍下三者. 这三者在C++中都是标准IO库中提供的输出工具(至于有关的重载问题在此不讨论): cout:写到标准 ...

  2. 83、源代码管理工具(Git)

    一.简介 git是一款开源的分布式版本控制工具 在世界上所有的分布式版本控制工具中,git是最快.最简单.最流行的 git起源 作者是Linux之父:Linus Benedict Torvalds 当 ...

  3. 神经网络参数与TensorFlow变量

    在TensorFlow中变量的作用是保存和更新神经网络中的参数,需要给变量指定初始值,如下声明一个2x3矩阵变量 weights =tf.Variable(tf.random_normal([2,3] ...

  4. [Java算法] -- 1. 常用排序之冒泡排序和选择排序

    使用Java语言实现冒泡排序和选择排序 推荐一个数据结构可视化的网站:http://zh.visualgo.net/zh (暂时访问不了) 对排序不太熟悉的朋友,建议去上面的网站学习一下,你将会发现一 ...

  5. Error resolving template [xxx], template might not exist or might not be exist

    Springboot+thymeleaf+mybatis 抛Error resolving template [xxx], template might not exist的异常 原因是我们在pom. ...

  6. 关于H5在微信获取授权

    很尴尬,flag倒了很久,这才来更新. 1.作为一枚小前端,所做的就是把微信获取授权之后的链接和所需的参数给到后端,定好之后只要获取链接就好了.(⊙o⊙)…确实就是这么简单,基本上这种授权是需要后端来 ...

  7. python循环解压rar文件

    python循环解压rar文件 C:. │ main.py │ ├─1_STL_算法简介 │ STL_算法简介.rar │ └─2_STL_算法_填充新值 STL_算法_填充新值.rar 事情是这样的 ...

  8. 【洛谷P3369】【模板】普通平衡树题解

    [洛谷P3369][模板]普通平衡树题解 题目链接 题意: 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3 ...

  9. Servlet的创建二以及生命周期

    之前说Servlet可以通过实现Servlet接口来创建,但是我们看到了,需要重写该接口中的所有方法. 创建方式二:Servlet的创建还可以继承抽象类GenericServlet并重写其中的抽象方法 ...

  10. JAVA课程设计---学生基本信息管理系统

    1.团队课程设计博客链接 http://www.cnblogs.com/zyjjj/p/7061880.html 2.个人负责模块或任务说明 函数 功能说明 Search 查找学生信息,分为两种查找方 ...