XMPP 协议简单参考

本贴最后更新于 3035 天前,其中的信息可能已经时移世改

最近写即时通讯的时候用到了XMPP协议,XMPP协议是用于即时通信的一个基于xml的通讯协议,开源的服务器又Openfire等,这里就不啰嗦了,本篇文章主要介绍XMPP协议本身。

在这里把对它的理解以及大体结构记录一下,留作备忘。

概览

(引自百度百科)

XMPP是一个流化XML[XML]元素的协议,用于准实时的交换消息和出席信息。XMPP的核心功能定义在Extensible Messaging and Presence Protocol (XMPP): Core [XMPP-CORE|XMPP文档列表/XMPP正式RFC标准/RFC3920]. 这些功能 -- 主要是 XML流, 使用 TLS和SASL,以及流的根元素之下的<message/>, <presence/>, 和 <iq/> 子元素 -- 为各种类型的准实时应用提供了一个构造基础, 它可以被放在核心的顶层,使用特定XML名字空间[XML-NAMES]发送特定的应用数据. 本文描述XMPP核心功能的扩展和应用,XMPP核心功能提供了RFC 2779 [IMP-REQS]定义的基本的即时消息和出席信息功能。 

登陆

XMPP协议这里我用的是TCP长连接进行的,连接上后,你需要向发送一个XML文档头,用来请求会话。

请求会话

向服务器发送以下文档头:

<?xml version="1.0"?>
    <stream:stream xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" to="server.im.321aiyi.com.com" version="1.0">

说明

在这个头中,包含一个<stream:stream>节点。这个节点标识一个会话的建立。当向发送</stream:stream>后,该会话结束。

xmlns:该属性通常拥有两个可选值,一个是jabber:client,一个是jabber:server,分别代表客户端和服务端。我这里是作为客户端连接的,因此值为jabber:client

xmlns:stream:对该协议的一个约束,固定值http://etherx.jabber.org/streams

to:表示接收者,也就是该条请求的发送目标。向服务器建立会话时,可以直接填写服务器地址,如server.im.321aiyi.com

服务器响应

<?xml version='1.0' encoding='UTF-8'?>
    <stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" from="server.im.321aiyi.com" id="6e0bov7s32" xml:lang="en" version="1.0">
        <stream:features>
            <starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"></starttls>
            <mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
                <mechanism>PLAIN</mechanism>
                <mechanism>ANONYMOUS</mechanism>
                <mechanism>SCRAM-SHA-1</mechanism>
                <mechanism>CRAM-MD5</mechanism>
                <mechanism>DIGEST-MD5</mechanism>
            </mechanisms>
            <compression xmlns="http://jabber.org/features/compress">
                <method>zlib</method>
            </compression>
            <auth xmlns="http://jabber.org/features/iq-auth"/>
            <register xmlns="http://jabber.org/features/iq-register"/>
        </stream:features>

说明

服务器会响应给你一个新的<stream:stream>会话,大概是询问你需要什么方式验证并连接。你需要接着这个会话回应服务器

<stream:features>:该节点中列出了可供选择的验证方式

<starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"></starttls>:表示服务器支持开启TLS安全传输协议

<mechanisms>:节点中有一些选项,表示服务器支持的验证方式。分别代表:

    PLAIN:简单验证,直接使用Beans64编码

    ANONYMOUS:匿名登录(服务器会分配给你一个临时的账户)

    SCRAM-SHA-1:后面的这些在网上页找不到相关的资料,所以我也不知道具体是什么意思。有时间我得买本书看看

<compression>:节点表示服务器支持压缩并列出了支持的压缩方案

<autch>:表示支持账号密码认证

<register>:表示支持注册

采用已有账号进行简单登陆

这里我选择PLAIN验证方式,并使用账号密码直接登陆。这种验证最简单

假设我的账号是admin密码是admin123的话,我将账号和密码这样拼接:"\0admin\0admin123"并进行Base64编码得到最终的值

String value = Hash.BASE_UTIL.encode("\0admin\0admin123");

//value = AGFkbWluAGFkbWluMTIz

将编码后的账号密码发使用 auth 标签发给服务器进行登陆

<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>AGFkbWluAGFkbWluMTIz</auth>

说明:

xmlns 的值表示已 sasl 的方式传输

mechanism 的值表示已 PLAIN 方式验证,也是最简单的验证方式

节点中的内容就是账号密码进行 base64 编码后的值

服务器回应:

<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>

说明:

成功通过验证并确定数据交流方式为 sasl 方式。

绑定资源

绑定资源就是声明一下你当前所使用的客户端资源类型。说白了就是你的客户端类型。比如 Windows、Surface、Lumia、WEB、Android 等。这事可以自定义的。比如 asdasdasd 也是可以的。

<iq type='set' id='bind_2'>  
    <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>  
        <resource>Windows</resource>  
    </bind>  
</iq>

说明:

<iq>:这种节点一般用与服务器的交互,待会儿再系统的说,现在说的话一些新手反而会手忙脚乱,比如说我这样的。

<bind>:表示我要进行资源绑定操作!

<resource>:我要绑定的资源名。因为我是开发 Windows 客户端,所以我把资源名定为 Windows,然后我就可以显示 Windows 在线了

服务器响应:

<iq type="result" id="bind_2" to="server.im.321aiyi.com/5tpldmpwov">
    <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">
        <jid>admin@server.im.321aiyi.com/Windows</jid>
    </bind>
</iq>

说明:

type:表示服务器响应的状态,值为 result 表示绑定成功。

id="bind_2":表示绑定的类型是自定义资源类型。

<bind>:服务器回应你绑定的资源内容

<jid>:绑定后,服务器分配给你的 JID,JID 表示一个用户。(最简单的 JDK 由 账号 + @ + 服务器地址三部分构成),同样留在后面讲

设置用户状态

验证成功 bi 后,其实你已经在线了,只不过别人不知道。准确的说,你现在是隐身的。你已经可以和别人对话并接收别人给你发的消息了。这个时候,你要告诉大家伙:“喂!我来勒!”所以,你要声明一下你目前的状态为在线状态。

当然,除了在线状态之外,还有离线状态、忙碌、什么的一大堆(可选值:online、away、dnd)。

<presence from='admin@server.im.321aiyi.com/Windows' to='server.im.321aiyi.com'> 
    <status>Online</status>
</presence>

说明:

<presence>:表示出席,也就是出场、来到的意思,其实说白了就是上线

from:出席来源,来源是我,所以这里的值写我的 JID

to:出席目标,我要去哪里出席,我在整个服务器上出席,服务器的所有人都能看到我在线,所以我给他的值写 server.im.321aiyi.com(假如入我只给某个人出席的话,就把服务器地址改为对方的 JID,同理,我只对某人隐身的话,就现在服务器出席,然后再对某人单独已隐身状态下出席)

<status>:表示出席状态,比如我要以在线状态出席,那么我写 Online

服务器响应:

<presence from="sys@server.im.321aiyi.com/Windows" to="admin@server.im.321aiyi.com/Windows">
    <priority>0</priority>
    <status/>
    <x xmlns="urn:xmpp:rooyee:message:state:v1"/>
</presence>

说明

表示 sys 这个用户知道了你的出席,并告诉你了 sys 这个用户的出席状态

发送一个简单的消息

加入我要给 sys 这个用户私发一条内容为“你好!”的消息,我可以这么写。

<message from="admin@server.im.321aiyi.com/Windows" to="sys@server.im.321aiyi.com" type="chat">
    <body>你好!</body>
</message>

说明:

<message>节点表示发送或接受一条消息,这里简单的说一下,系统的解释后面说。

type="chart":表示消息的类型,我是一条私聊的消息

<body>:该节点中是消息的内容

IQ 语法

IQ 分别代表 Info 和 Query。IQ 在 XMPP 中是一个节点,该节点通常用于与服务器的信息查询与提交。类似 HTTP 协议中的的 GET 与 POST 的关系。

利用 IQ 节点请求服务器的话,服务器都将必须给予一个响应。所以 IQ 节点中必须通过一个 id 属性,来保持一个消息的通道。

举个简单的例子,假如服务器向我发送<iq id="1" />的话,我如果响应<iq id="2" />的话,那么抱歉,服务器并不会认账。他不会认为你向服务器发送的那个 iq 是响应之前的请求的。

另外,IQ 的 type 属性也是必填的,type 属性拥有四种值:

get,表示查询请求;

set,表示提交请求;

result,表示成功响应请求的结果;

error,表示处理请求失败。

下面举一个例子:

请求我的花名册

客户端请求数据:

<iq from="jane@longbourn.lit/garden" type="get" id="roster1">
    <query xmlns="jabber:iq:roster"/>
</iq>

说明:

客户端发送了一个获取花名册的请求,xmlns="jabber:iq:roster"表示获取花名册。

服务器响应:

<iq to="jane@longbourn.lit/garden" type="result" id="roster1">  
    <query xmlns="jabber:iq:roster">  
        <item jid="elizabeth@longbourn.lit" name="Elizabeth"/>  
        <item jid="bingley@netherfield.lit" name="Bingley"/>  
    </query>  
</iq>

说明:

服务器响应了花名册的内容

rype="result"表示响应成功,

id="rester1"表示我响应的是之前发送的 id 为 roster1 的请求,即花名册请求。

<query xmlns="jabber:iq:roster">是服务器响应的花名册结果集。

<item>就是花名册中的每个成员。


在我的花名册中添加一个成员

<iq from="jane@longbourn.lit/garden" type="set" id="roster3">
    <query xmlns="jabber:iq:roster">
    <item jid="darcy@pemberley.lit" name="Mr. Darcy"/>
</query>
</iq>

说明:

这里表示把账号为 darcy 的用户添加到我的花名册中,并设置备注为“Mr. Darcy”

服务器响应:

<iq to="jane@longbourn.lit/garden" type="result" id="roster3"/>

说明:

成功添加到化名侧


相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...