xmppmini 项目详解:一步一步从原理跟我学实用 xmpp 技术开发 3.第一句消息的解码及解码的原理
浏览(625 + ) 作者: clq 发表于 2020-09-23 14:03:19
编辑
关键字:
xmppmini 项目详解:一步一步从原理跟我学实用 xmpp 技术开发 3.第一句消息的解码及解码的原理 这系列文章比较关键,读者未必能全部看懂,所以我决定把每篇该站都在这里做一个拷贝。同时相应的修改也在这里修改,而且有些地方发文后就不让修改了,实在不便。 读者具体对哪一章节的哪部位内容有疑问也方便直接跟帖提问。 ---------------------------------------------------------------- 首发地址 https://www.cnblogs.com/-clq/p/13717496.html ---------------------------------------------------------------- xmppmini 项目详解:一步一步从原理跟我学实用 xmpp 技术开发 3.第一句消息的解码及解码的原理 xmpp 协议的这个名称就来自于它的消息包格式借鉴了 xml 的格式,但并不是我们常规编程中的那种完整的 xml 信息包。因此就不能用普通的 xml 解码库来操作这些消息,一般的情况下是需要另外开发的,而实际的开发中通常使用第三方库。但就目前的第三库现状来说,可以说是不怎么好用,所以我们来看看如何手工自己进行消息的解码。 首先第一句话就是一个坑,以我们前面提到的从服务器中收到的第一句为例: <?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 的封装形式而已。 在 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”,如果有,就说明已经收完了第一个包,服务器告诉我们可以发送登录信息了。伪码如下: if FindStr('mechanism', gRecvBuf) { [做登录的各种动作] } 但这样其实也不对!因为,含有“mechanism”并不能说明整个登录包结束了,还记得我们前面学习 SMTP/POP3 是如何判断一个包什么时候结束了吗?一般情况下是判断是否有“\r\n”,xmpp 协议其实也是判断是否有某个结束符字符串,只不过这个结束符号不是固定的,而是针对不同的命令而不同而已!这就是 xmpp 协议操作中最关键的部分。实际上不光 xmpp 包括 SMTP/POP3 以及我们还计划要解说的 http 协议的操作中最关键的就是要找到一个包结束的位置和方法,解决了这个问题就可以说成功了一大半。 而对于我们现在的这个包,它的结束符号是 “</mechanism>”,这里就要涉及到 xml 格式的知识了,如果一个 xml 节点中还有子节点的话,它必须包括一个 </[节点名]> 这样的尾部。所以我们直接利用这一点,在gRecvBuf 中查找到这个字符串就是它的包尾了。 了解 xml 格式的读者可能就会提问说,如果mechanism 节点里还有mechanism 子节点,这个方法就不行了。没错,但是刚好 xmpp 协议中是没有这种情况的,所以我们可以放心地使用这种方式。其实就算有这种情况,我们再做进一步处理即可,只是根据 xmpp 协议的特点,没有必要那样做。所以实际上正确的操作伪码应该是: if FindStr('</mechanism>', gRecvBuf) { [做登录的各种动作] } 这其中要注意的是,查找字符串函数应该是忽略大小写的。因为节点名是有可能含有大小写混用的情况的,出于兼容性的考虑,能忽略大小写是最好的。 这是非常重要的一个章节,建议大家仔细反复研究一下,虽然内容不多,但这是我们整个 xmpp 协议消息包处理的中心思想,非常的关键,也非常的简洁有效。 ---------------------------------------------------------------- 本文计划加入实体书《一步一步从原理跟我学网络协议编程 第一辑 email xmpp http ftp》,欢迎有意的出版社与我联系。email: clq_work@163.com or clq@newbt.net 陈立强 出版之前读者需要实体书也可以和我联系。实体书的内容更完整、更正式,一些章节也只在实体书中(主要是一些修改和补充的内容我就没有精力一一在网络各处更新了),而且从个人学习的经历来说,感觉实体书的作用还是有其不可替代的地方的。好多国外的技术作者出了完整的网络版本外也仍然出了实体书就是这个道理了。谢谢您的支持。
[2020-09-23 14:36:44 最后更新]
NEWBT官方QQ群1: 276678893
可求档连环画,漫画;询问文本处理大师等软件使用技巧;求档softhub软件下载及使用技巧.
但不可"开车",严禁国家敏感话题,不可求档涉及版权的文档软件.
验证问题说明申请入群原因即可.