xmppmini 项目详解:一步一步从原理跟我学实用 xmpp 技术开发 3.第一句消息的解码及解码的原理

    xmpp 协议的这个名称就来自于它的消息包格式借鉴了 xml 的格式,但并非咱们常规编程中的那种完整的 xml 信息包。所以就不能用普通的 xml 解码库来操做这些消息,通常的状况下是须要另外开发的,而实际的开发中一般使用第三方库。但就目前的第三库现状来讲,能够说是不怎么好用,因此咱们来看看如何手工本身进行消息的解码。html

首先第一句话就是一个坑,以咱们前面提到的从服务器中收到的第一句为例:程序员

 

<?xml version='1.0'?>

<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' from='xumatomacbook-pro.local' id='675c6847-c13d-4710-9844-d9339e4df087' version='1.0' xml:lang='en'>

 

乍一看上去,你会觉得第一句话是 “<?xml version='1.0'?>”,好咱们开始解码这句话吧。答案是 NO !这句话是无关紧要的,因此咱们解码的第一个工做就是判断起始句是 xml 部分仍是后面的 stream 部分。编程

    实际上咱们的作法是根本不解码!读者必定瞠目结舌不敢相信,对的,实际上咱们对 xmpp 协议进行操做根本不须要 xml 解码器,只使用几个字符串查找和截取函数就能够了!服务器

    可以这样作的根本缘由就在于 xmpp 协议并非完整的 xml 包,实际上它和咱们前面文章中的 SMTP/POP3 协议同样是服务器与客户端的一问一答式的问答包(固然也还不彻底是,咱们后面会说到),只是借助了 xml 的封装形式而已。socket

在 xmpp 协议中,服务器发出第一句话以后就立刻要发送登陆方法说明包,即函数

<stream:features><mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><mechanism>PLAIN</mechanism></mechanisms></stream:features>

相似于这样的格式。实际上咱们在操做中直接将它们当作一个包处理就好了,就是说能够直接忽略掉第一个包,无论它有没有“<?xml version='1.0'?>”。在编程上就是一直读取服务器 socket 中的内容,咱们将当前读取到而没有处理的内容当作一个字符串(而不是 xml 流),给它一个变量名为gRecvBuf学习

而后每当 socket 接口上有数据来到事件时就去检测gRecvBuf 中是否已经包含了字符串“mechanism”,若是有,就说明已经收完了第一个包,服务器告诉咱们能够发送登陆信息了。伪码以下:atom

 

if FindStr('mechanism', gRecvBuf) {

  [作登陆的各类动做]

}

 

    但这样其实也不对!由于,含有“mechanism”并不能说明整个登陆包结束了,还记得咱们前面学习 SMTP/POP3 是如何判断一个包何时结束了吗?通常状况下是判断是否有“\r\n”,xmpp 协议其实也是判断是否有某个结束符字符串,只不过这个结束符号不是固定的,而是针对不一样的命令而不一样而已!这就是 xmpp 协议操做中最关键的部分。实际上不光 xmpp 包括 SMTP/POP3 以及咱们还计划要解说的 http 协议的操做中最关键的就是要找到一个包结束的位置和方法,解决了这个问题就能够说成功了一大半。spa

而对于咱们如今的这个包,它的结束符号是 “</mechanism>”,这里就要涉及到 xml 格式的知识了,若是一个 xml 节点中还有子节点的话,它必须包括一个 </[节点名]> 这样的尾部。因此咱们直接利用这一点,在gRecvBuf 中查找到这个字符串就是它的包尾了。3d

了解 xml 格式的读者可能就会提问说,若是mechanism 节点里还有mechanism 子节点,这个方法就不行了。没错,可是恰好 xmpp 协议中是没有这种状况的,因此咱们能够放心地使用这种方式。其实就算有这种状况,咱们再作进一步处理便可,只是根据 xmpp 协议的特色,没有必要那样作。因此实际上正确的操做伪码应该是:

 

if FindStr('</mechanism>', gRecvBuf) {

  [作登陆的各类动做]

}

 

这其中要注意的是,查找字符串函数应该是忽略大小写的。由于节点名是有可能含有大小写混用的状况的,出于兼容性的考虑,能忽略大小写是最好的。

这是很是重要的一个章节,建议你们仔细反复研究一下,虽然内容很少,但这是咱们整个 xmpp 协议消息包处理的中心思想,很是的关键,也很是的简洁有效。

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

版权声明:

本系列文章已受权百家号 "clq的程序员学前班" . 文章编排上略有差别.