使用Node.js和Docker的可扩展消息和存在协议--XMPP
可扩展消息与存在协议(XMPP)是一个开放的通信协议,用于即时通信的存在信息和联系人列表的维护。
本教程将带领你了解XMPP架构的概念,它是如何工作的,并使用Node.js和docker建立一个演示服务器连接。
前提条件
要轻松地跟上本教程,应该满足以下要求。
- 对Node.js的编程和Docker命令有基本的了解。
- 一个预装的IDE,最好是[Visual Studio Code]。
- 对[Docker]有基本的了解。
- 对[Node.js]有基本的了解。
主要收获
在本教程结束时,你应该明白。
- 为什么我们需要XMPP?
- 底线架构和它的工作原理。
- XMPP传输。
- 使用Node.js和Docker的XMPP服务器演示。
为什么是XMPP?
XMPP是Extensible Messaging and Presence Protocol的缩写,是一个开放的标准,通过管理网络上的XML数据交换,支持近实时的聊天和即时通讯。
XMPP允许XML数据,以短文段的形式,使用互联网的传输控制协议(TCP)从一个终端可靠地发送到另一个终端,沿途要经过一个中间服务器。
XML,即可扩展标记语言,提供了一个框架,用于存储和组织文档中的纯文本数据,这样,无论其硬件或软件配置如何,这些数据都可以被各种网络终端轻松解释。
当在后端使用时,它给出了一个直接的链接,几个客户通过它进行连接。它有一个分散的协议,允许属于不同的XMPP服务器的客户与它进行通信。
XMPP架构
在这一节中,让我们看看这项技术的架构和它的内部工作方式。为了便于在网络上进行路由,所有的XMPP地址都是全球可寻址的。
它的设计是使用XML流标签,即<stream:stream /> 。这是通过在每个元素中发送XML句子来实现的,而不需要等待整个文件被完全发送。
还有一种通过询问客户是否支持某种类型的协议、加密等功能的协商。同样,这可以在XMPP协议的基础上完成。
XMPP支持三种不同的XML句子。
以下是这些句法。
- 消息可以用XML标签发送。
- 状态也可以像这样进行交换。
- 信息查询,这是请求-回应的liketag。
最后,整个XMPP是分散的。这意味着没有一个客户端是直接连接到另一个客户端的。相反,连接是由服务器作为客户端之间的中介来实现的。
让我们假设我们有一个域名myxmpp.com 作为两个客户之间的服务器。下面的例子显示了如何建立连接。
ClientA 连接到xmpp服务器。
<stream:stream
from='a@myxmpp.com'
to='myxmpp.com'
version='1.0'
xmlns='jabber:client'
>
而另一个客户,ClientB 连接到xmpp服务器。
<stream:stream
from='b@myxmpp.com'
to='myxmpp.com'
version='1.0'
xmlns='jabber:client'
>
ClientA 通过服务器向 发送一个消息。ClientB
<message to='b@myxmpp.com'>
<body>Hello </body>
</message>
然后ClientB 收到来自ClientA 的消息,如下所示。
<message from='a@myxmpp.com'>
<body>Hi </body>
</message>
客户端A终止了流。
</stream:stream>
上面的代码片段显示了这个XMPP服务器的结构。这就是服务器如何通过使用定义的stream 的属性来连接不同的客户端。
每个流标签都有from,to,version 和xmlns 参数。是服务器根据注册时提供的客户详细资料预先填入这些参数的。
不用担心,当我们建立一个演示时,所有这些很快就会被清除掉。
XMPP传输
XMPP是建立在传输控制协议TCP 上的一种不可知的传输方式。服务器运行的默认端口是5222 。这个服务器可能会被防火墙屏蔽,因为它不喜欢随机端口。
通过在HTTP上托管XMPP服务器,并进行长时间的轮询,可以避免这种情况,因为它只在服务器收到新的请求时发送消息。也就是说,HTTP不是双向的,是无状态的。
使用Node.js和docker的XMPP服务器演示
在这个演示中,我们用docker旋转了XMPP服务器ejabberd ,因为这是最简单的方法。我们将创建两个用户,启动Node.js XMPP客户端以连接到服务器,然后进行聊天。我们必须使用下面的命令创建一个ejabberd 实例图像。
docker run --name ejabberd -p 5222:5222 ejabberd/ecs
上面的命令将运行ejabberd ,XMPP服务器在端口5222 ,并创建其docker镜像与ejabberd/ecs 。
现在继续并打开另一个终端,用下面的docker命令注册这两个客户端。
docker exec -it ejabberd bin/ejabberdctl register admin localhost mypassword1
Docker使用ejbberd/bin/ejabberdctl ,用提供的凭证注册一个新的用户。关键字admin 是第一个用户的名字。而localhost ,则是指向你机器的本地IP。
注意:如果需要另一个IP地址,这可以被改变。然而,现有的域名也可以使用。
注册成功后,它将返回一个信息User admin@localhost successfully registered 。
注意,根据你的设置,输出结果可能有所不同。
此外,我们将用同样的程序注册另一个用户。
docker exec -it ejabberd bin/ejabberdctl register myself localhost mypassword2
注册成功后,会返回一个消息User user2@localhost successfully registered 。那么,我们如何将这两个客户端与服务器连接起来呢?
这就是Node.js的作用。我们使用该框架来编写客户端之间连接的服务器代码。
打开你喜欢的代码编辑器,创建一个Node.js项目,如下所示。
$ npm init .
$ npm install simple-xmpp
上面的JavaScript代码片段创建了一个新的项目目录,其中包含package.json 文件。这个文件跟踪你的项目所需的所有依赖性。
安装的simple-xmpp 是在不同客户端之间启动XMPP服务器连接所需的库。由于没有给出--save-dev 命令,所以这是全局安装的。
在有package.json 的项目目录下,创建admin.js 和myself.js 文件。我们用服务器-客户端连接来编辑这些文件。
admin.js 的代码在下面的片断中给出。
// we bring in the server library
const xmpp = require("simple-xmpp");
// this function recursively call itself by sending the provided message every 5 seconds.
function send(){
setTimeout(send, 5000);
xmpp.send("myself @localhost", `hi! Today is ${new Date().toLocaleString()}`)
}
//if online, that is connected to the server the send function will be excuted and log to console
xmpp.on("online", data => {
console.log("hello, you are live!");
console.log(`Connected as ${data.jid.user}`);
send();
});
// if chat was received from other client, the log will be executed
xmpp.on("chat", (from, message) => {
console.log(`Got a message! ${message} from ${from}`)
})
// connect method requires object with paramters below
xmpp.connect({
"jid": "admin@localhost",
"password": "mypassword1",
"host": "localhost",
"port": 5222
})
simple-xmpp 库有不同的参数被调用。例如,在上面的代码片段中,我们在online 和chat 的参数上调用了on 方法。
一旦管理员用户连接到服务器,on 方法就会将连接识别为online ,并执行回调函数。
然而,该库的on 方法只有在收到其他客户端的任何消息时才会执行chat 参数的回调函数。simple-xmpp 库有connect() 方法,需要不同的属性。
jid 作为每个客户端的身份,这是从上面的注册中返回的。所有其他参数是password ,host ,和port 。
另一个客户端也需要同样的连接,但参数不同。因此,在下面找到myself.js 文件的片段。
const xmpp = require("simple-xmpp");
function send(){
setTimeout(send, 5000);
xmpp.send("admin@localhost", `hi! Today is ${new Date().toLocaleString()}`)
}
xmpp.on("online", data => {
console.log("hello, you are live!");
console.log(`Connected as ${data.jid.user}`);
send();
});
xmpp.on("chat", (from, message) => {
console.log(`Got a message! ${message} from ${from}`)
})
xmpp.connect({
"jid": "myself@localhost",
"password": "mypassword2",
"host": "localhost",
"port": 5222
})
现在,打开到不同的代码编辑器终端,运行下面的命令。确保你cd ,进入项目目录。
从第一个终端,运行下面的代码。
node admin.js
运行这个命令后,你将收到从on() 方法的online 参数中记录的信息。
该日志信息将是这样的。
Hey, you are online!
Connected as user1
在第二个终端运行这个命令,会调用另一个客户-服务器。
node myself.js
现在,两个客户端都连接了,send() 函数的消息体将开始每隔5 秒向两个连接弹出。有了这个连接,我们就实现了本教程的目标。
总结
本教程介绍了意义的概念,下划线架构,以及XMPP服务器如何工作。我们还使用Node.js建立了一个演示连接,并使用docker来旋转服务器镜像来注册客户端。