linux-Tcp IP协议栈源码阅读笔记(转)

XMPP协议介绍

simplyzhao posted @ 2009年10月05日 03:20 in Network Programming with tags Gtalk XMPP , 3792 阅读

网上摘录

1、什么是XMPP ?
XMPP的前身是Jabber,一个开源形式组织产生的网络即时通信协议。XMPP目前被IETF国际标准组织完成了标准化工作。标准化的核心结果分为两部分;
核心的XML流传输协议
基于XML流传输的即时通讯扩展应用
XMPP的核心XML流传输协议的定义使得XMPP能够在一个比以往网络通信协议更规范的平台上。借助于XML易于解析和阅读的特性,使得XMPP的协议能够非常漂亮。
XMPP的即时通讯扩展应用部分是根据IETF在这之前对即时通讯的一个抽象定义的,与其他业已得到广泛使用的即时通讯协议,诸如AIM,QQ等有功能完整,完善等先进性。

2、XMPP的基本网络结构是怎样的?
XMPP中定义了三个角色,客户端,服务器,网关。通信能够在这三者的任意两个之间双向发生。服务器同时承担了客户端信息记录,连接管理和信息的路由功 能。网关承担着与异构即时通信系统的互联互通,异构系统可以包括SMS(短信),MSN,ICQ等。基本的网络形式是单客户端通过TCP/IP连接到单服 务器,然后在之上传输XML。

3、XMPP通过TCP传什么了?
传输的是与即时通讯相关的指令。在以前这些命令要么用2进制的形式发送(比如QQ),要么用纯文本指令加空格加参数加换行苻的方式发送(比如MSN)。而 XMPP传输的即时通讯指令的逻辑与以往相仿,只是协议的形式变成了XML格式的纯文本。这不但使得解析容易了,人也容易阅读了,方便了开发和查错。而 XMPP的核心部分就是一个在网络上分片断发送XML的流协议。这个流协议是XMPP的即时通讯指令的传递基础,也是一个非常重要的可以被进一步利用的网 络基础协议。所以可以说,XMPP用TCP传的是XML流。

 

--------------------------------------------------------------------------------------------

来源: 云风的BLOG blog.codingnow.com/2008/11/xmpp.html

我最常用的 IM 是 google talk ,本身就实现了标准的 XMPP Client 和 XMPP Server 协议;而我们的 网易 popo 也实现了 XMPP 的 s2s 网关。我想研究一下 XMPP 是个不错的选择。

花了一整天的时间,把 XMPP 核心协议 仔细通读了一遍,收获颇多。原来以为 XMPP 是个可怕的巨无霸。我对 XML 原本也没有太多好感。最后,看法有所改变。

其实,XMPP 仅仅是定义了一个网络服务间相互通讯的协议。它已经把服务间需要关心的东西减少到了最少。具体的应用每家服务提供商可以随意扩展。popo 在制作新版本时,我曾多次建议采用已有的标准协议,再此基础上开发自己的东西。当时或许大家都认为标准协议容易促手促脚,我当时也没啥研究,没有多言。今 天看来,我更觉得这是一个决策失误。本来我们有一个很好的机会,利用 popo 联系起网易的各种服务,现在这条路将走的更为艰辛。其实,XMPP 定义的东西,即使自己去设计也会定义出类似的一套来。而把各种网络服务互通本该是发展的重点,为 IM Client 增添专有花哨的特性就有些舍本逐末了。更为恼火的是,popo 到现在也没有一个很好的非 Windows 平台解决方案。怎能让诸多把握着互联网上部分话语权的技术人士接受?(或者,同在杭州的 IT 圈子,popo 的开发人员是不是应该看看支付宝的同行们做了些什么?)

谈谈我对 XMPP 的粗浅理解。这些仅仅建立在我对 RFC3920 的一天阅读的基础上,难免会有错误,不足以做技术参考。

XMPP 抽象出一个在互联网上唯一的对象实体,用 JID 来表达。通常一个 JID 由三部分组成,node@domain/resource 。比 email 的表达形式多了一个 /resource 。这是因为 email 地址本身虽然可以表达一个实体,都是往往不够表达这个实体下的具体服务。就好比一个 ip 地址可以表示一台机器,但是我们还需要 port 号来表达这台机器具体提供的服务一样。

用过 gtalk 的人应该很喜欢 gtalk 可以在不同的地方同时登陆这个不错的特性。用过以后,才能体会,无论是 qq 还是 msn 还是 popo ,只允许一个登陆是多么愚蠢的设定。gtalk 其实遵守了标准的 XMPP 协议,它用来区别一个帐号(一般是一个 gmail 邮件地址)的多处登陆,正是利用了不同的 resource 标识。

XMPP 规范的最重要的一条通信协议就是,如何把消息从一个 JID 发送到另一个 JID (message)。这有点像 email 协议,但不同的是,它强调了实时性和安全性(虽然不是必须的)。因为 JID 可以在不同的 domain 下,这就需要 domain 间相互协作。对于 IM 网络来说(XMPP 远不只用于 IM 协议),就是不同的 IM 服务间互通。

对于 domain 下的 xmpp 服务的发现,利用了 DNS 协议的一些功能。xmpp 的 s2s 服务提供位置,放在了 DNS 的 SRV 记录里。你可以用 nslookup 做个试验,启动 nslookup ,输入 set type=SRV

然后查询 _xmpp-server._tcp.gmail.com 你会发现 gmail.com 的 xmpp s2s 服务地址已经端口号 5269 。同样,也可以查询 _xmpp-server._tcp.163.com_xmpp-server._tcp.popo.163.com 查到网易 popo 的 xmpp 中转服务器地址。

btw, 查询 _xmpp-client._tcp.gmail.com 可以查到 gtalk 的 client 登陆地址,而网易 popo 则没有提供 xmpp client 登陆点。

按 RFC3920 所述,在 xmpp server 互联的时候,会优先尝试获取 domain 的 SRV 记录,如果失败就直接去连默认的 6259 端口。然后就可以开始握手协议。

xmpp 比较强调 s2s 的安全性,所以推荐的握手都是建立在 TLS 层之上,使用 SASL 认证。TLS 层需要服务器有一个数字证书,为了安全可信,建议是找个根证书签名。不过自己签名也行,只需要服务器缓存证书即可。握手过程在 RFC3920 中描述的非常细致,可以按照其编码,问题不大。需要注意的是,这里的 XML 流格式要求很精确,不允许传输多余的东西。我一度认为采用 XML 会导致协议的实现上非常臃肿,其实不然。采用 XML 只是一个表象,适合人阅读和调错而已。RFC 中特别要求不去实现 XML 中的某某特性就是一例。我们不应该为了 XML 而去 XML 。

其实 XMPP 的 c2s 和 s2s 并无太大区别,s2s 做的人手我想是因为开源项目和开源库比较少吧。而开源的 client 实现则是一大堆。c2s 和 s2s 的通讯都是基于那几条协议而已,s2s 的实现难点在于握手比较复杂(其实 c2s 也一样,只是很多库帮你做好了)。c2s 是共享一个 tcp 连接做双向通讯;而 s2s 则是用两条 TCP 连接。两条连接也一定程度上避免了 s2s 的欺骗,当然真正的安全来至于 TLS 和 SASL 的保障。DNS 毕竟是一个很脆弱的东西。

除了点对点消息外,XMPP 定义了消息的组播。也就是一个 JID 可以以自己的名义发布消息 (presence)。而服务器来决定该发给谁。发送目标是由订阅消息决定的。其它多个 JID 可以订阅某个 JID 的消息。对于 IM 来说,最常用的就是上线下线等状态变化消息了。

第三条即是对某个 JID 的状态进行设置和获取 (iq)。于 IM 应用来说,设置签名,昵称,状态等都依赖于它。

XMPP 的核心协议无非规定了以上三种通讯协议,此外规范了服务器间互连的握手认证方案。然后给出了一些错误信息的表述方法。稍微了解过之后,很容易编写。如果希 望重造轮子的话,对于 C 语言开发者来说,最繁琐的可能是 XML 的解析于生成。我自己稍微考察了一下,有个叫 LoudMouth 的库还不错。

如果实现 s2s 网关的话,有些细节做起来可能很麻烦,比如查询 DNS 的 SRV 记录。这个在 jabberd 1.x 里其实有独立的模块实现好了,取来用即可 (见 dnsrv) 。而 TLS SASL 层的实现则早就有现成的开源库了。

实现一个 jabber server 或许比你想象的还简单。in.jabberd 居然只用 600 多行 C 代码就从零实现了一个 jabber 服务器。当然功能非常的简陋了。

                     

 

-------------------------------------------------------------------------------------------------

规范:

核心的XML流传输协议 rfc3920
基于XML流传输的即时通讯扩展应用 rfc3921

英文不好的人还可以查看wiki.jabbercn.org/index.php 这是xmpp的中文网站,翻译了主要的xmpp协议。

另外,还有一篇tech.163.com/07/0627/16/3I0Q86FG000917GT.html

 

 

Enjoy Linux, Fighting.

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter