IM - XMPP简介
1. 概述
XMPP是一个可扩展的消息与空间协议(Extensible Messaging and Presence Protocol)。
该协议的前身是Jabber
(诞生于1999年),以XML为协议载体,具备良好的扩展性
。不仅可以传输简单的文本,而且可以携带复杂的数据和各种格式的文件,也就是说XMPP协议不仅可以用在人与人
之间的交流,而且可以实现软件与软件
或软件与人
之间的交流,目前支持XMPP协议的即时通讯工具有Gtalk、FaceBook IM、Twitter、网易POPO等等通讯工具。
XMPP有非常丰富的生态资源,例如
- 开源的Server/Client/Library
- 公开免费的Server服务
- 广泛的应用场景,包含IoT、Online Gaming、Social、WebRTC
如何快速开始XMPP之旅,可以参考:https://xmpp.org/getting-started/
本文重点介绍XMPP协议实现
、Openfire服务
、Gajim和Conversejs客户端
,对XMPP有一些初步的认识。
2. 协议介绍
2.1. 优缺点对比
优点
去中心化架构,支持c2s/s2s通信
有利于保障了数据安全
,且提高了整个XMPP网络的健壮性
支持扩展协议
Having 459 XEPs(XMPP Extension Protocols):https://xmpp.org/extensions/
Key XMPP technologies(XEPs):
- Core — information about the core XMPP technologies for XML streaming
- Jingle — SIP-compatible multimedia signalling for
voice, video
, file transfer, and other applications - Multi-User Chat — flexible, multi-party communication
- PubSub — alerts and notifications for data syndication, rich presence, and more
- BOSH — an HTTP binding for XMPP (and other) traffic
Jabber ID (JID)
Jabber Identifiers (JIDs) uniquely identify individual entities in the Jabber network.
- Template
<JID> = [<node>"@"]<domain>["/"<resource>]
- Example
UserID: h2018450@openfire.main.server
ServerID: openfire.main.server
分布式部署
缺点
- XML相比Json,略显臃肿
- 协议没有区分对待
控制信令
和数据传输
,比如从通信通道
、处理优先级
等方面
2.2. 协议样例
2.2.1. 三大顶层通信元素
<presence/>
- to exchange presence information
允许用户广播其在线状态和可用性,可以是online、offline、available、unavailable、hide等
<presence from=user1@jabber.org to=user2@jabber.org>
<status>online</status>
<presence/>
<iq/>
- for command exchanges
Information/Query,信息/查询请求,是一个请求/响应
机制,用来发送和获取
两个实体之间的信息,允许他们通过xml格式完成查询和响应
IQ元素用于不同的目的,它们之间通过不同的命名空间
来加以区分。在Jabber/XMPP消息协议里有许多的命名空间,最常用的命名空间是:"jabber:iq:register","jabber:iq:auth","jabber:iq:roster"
- 创建一个新session
c: <iq to='example.com' type='set' id='sess_1'>
<session xmlns='urn:ietf:params:xml:ns:xmpp-session'/>
</iq>
s: <iq from='example.com' type='result' id='sess_1'/>
<message/>
- to transfer messages
用于两个用户之间发送消息
<message from='juliet@example.com' to='romeo@example.net'>
<body>Are you ok?</body>
</message>
2.2.2. XMPP通信样例
... start a new xmpp stream as below ...
C: <?xml version='1.0'?>
<stream:stream
to='example.com'
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
version='1.0'>
S: <?xml version='1.0'?>
<stream:stream
from='example.com'
id='someid'
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
version='1.0'>
... encryption and resource binding ...
... authentication as below ...
C: <iq type='get' to='shakespeare.lit' id='auth1'>
<query xmlns='jabber:iq:auth'>
<username>bill</username>
</query>
</iq>
S: <iq type='result' id='auth1'>
<query xmlns='jabber:iq:auth'>
<username/>
<password/>
<digest/>
<resource/>
</query>
</iq>
C: <iq type='set' id='auth2'>
<query xmlns='jabber:iq:auth'>
<username>bill</username>
<password>Calli0pe</password>
<resource>office</resource>
</query>
</iq>
S: <iq type='result' id='auth2'/>
... simple chat as below ...
C: <message from='juliet@example.com'
to='romeo@example.net'
xml:lang='en'>
C: <body>Art thou not Romeo, and a Montague?</body>
C: </message>
S: <message from='romeo@example.net'
to='juliet@example.com'
xml:lang='en'>
S: <body>Neither, fair saint, if either thee dislike.</body>
S: </message>
... close stream as below ...
C: </stream:stream>
S: </stream:stream>
参考:https://wiki.xmpp.org/web/Programming_XMPP_Clients
3. 服务端
3.1. Openfire
An XMPP server licensed under the Open Source Apache License.
采用Java开发,Github拥有2.4K star,持续更新中。
3.1.1. 如何搭建
- 启动openfire服务
docker run --name openfire -d --rm \
-p 0.0.0.0:9090:9090 \
-p 0.0.0.0:5222-5223:5222-5223 \
-p 0.0.0.0:5269:5269 \
-p 0.0.0.0:7070:7070 \
-p 0.0.0.0:7443:7443 \
-p 0.0.0.0:7777:7777 \
-v `pwd`/data:/var/lib/openfire \
gizmotronic/openfire:4.4.4
- 访问9090端口,配置postgres数据库(也可以选择
embedded database
)
Database URL: jdbc:postgresql://10.211.28.93:35432/openfiredb
Username/Password: openfire/openfire
openfire dashboard
3.1.2. 测试登录、注册和收发消息
- 通过
Client
或Openfire Dashboard
可以完成新用户注册
http://10.211.28.93:9090/user-summary.jsp
-
通过两个客户端
Conversejs
或Gajim
可以完成用户登录与收发消息 -
通过
Openfire Dashboard
可以完成对所有在线用户
的消息广播
3.1.3. 增加两个plugin
56个Plugins,包含websocket、restful-api、draw-io、emails等功能:
https://www.igniterealtime.org/projects/openfire/plugins.jsp
尝试了两个:
- inVerse: Adds the (third-party, Converse-based) inVerse web client to Openfire.
- Openfire Meetings: Provides high quality, scalable video conferences.
3.2. Ejabbed
Robust, Scalable and Extensible Realtime Platform (XMPP, MQTT, SIP Server).
采用Erlang开发,Github拥有4.9K star,持续更新中。
3.3. Jackal
An XMPP server written in Go.
采用Go开发,Github拥有1.1K star,持续更新中。
4. 客户端
4.1. Gajim
A fully-featured XMPP client.
采用Python3+GTK开发,支持主流OS,包含Windows/Linux/MacOS等。
Screenshots
contact listtabbed chat
groupchat window
4.2. Conversejs
A free and open-source XMPP chat client in your browser.
Converse is a web based XMPP/Jabber chat client.
You can either use it as a webchat app, or you can integrate it into your own website.
It's 100% client-side JavaScript, HTML and CSS and the only backend required is a modern XMPP server.
Screenshots
login window chat window5. 总结
XMPP历史悠久,生态也很健全。如果对XMPP/Openfire采用的技术不介意,且比较擅长,例如Java开发语言、XML数据流、单体服务,可以在此基础上二次开发。
其实,现在的互联网环境和10几年前相比有很多不同,例如微服务架构、消息中间件、内存数据库、Json数据、Go/Python高级开发预研等。如果IM是核心功能,而不是附属功能的话,建议自行开发设计,可以参考XMPP/Openfire/Gajim/Conversejs等优秀技术。
6. Next
- Openfire集群搭建
- Openfire内部架构与实现探究
7. 扩展
四种即时通讯协议对比参考。其中,XMPP应用更广泛,在多个方面更有优势。
- IMPP(Instant Messaging And PresenceProtocol): 即时信息和空间协议
- PRIM(Presence and Instant Messaging Protocol): 空间和即时信息协议
- SIP(Session Initialion Protocol): 回话发起协议
- XMPP(Extensible Messaging and Presence Protocol): 可扩展消息与存在协议