XMPP文件传输(XEP-0096协议说明)

XMPP XEP-0096协议是XMPP中的文件传输协议。
       关于文件传输,在xmpp协议中有不少协议可以实现,而XEP-0096协议是其中非常简单的一个协议。由于邮件被删,我的代码demo丢失,因此只能在这里给大家讲一下其中的逻辑实现,大家可以以此来写出代码。

       首先申明一下,以下是我个人对XEP-0096协议的一些认识和解释,如有疑问,请发邮件到lizhanzhishang@gmail.com ,欢迎交流~

       我们根据openfire服务器做开发,但是服务器在这里只是起路由寻址和转发的作用,实质上是完全点对点的通信,数据处理由客户端来做。

       我们可以举一个栗子,有两部手机,互相之间使用message协议传递信息的完整message XML数据,可以看看一个客户端发送的是什么信息,另一个客户端接收的又是什么message信息,要是一样,说明的是服务器是转发的数据,要是不一样的 话,则可能带有IQ ,MSG,Pr信息。(但是总是有例外的,服务器也要对连接的数据做一些心跳包。)

       下面是一组请求(一方发出“发送文件”请求,接收方发出“拒绝接受”请求):
       这是”发送文件”的一段数据请求,(图片小,可以双击放大)
22175447_3u76.png

      将接受方拒绝接受文件的信息返回给发送方:
22175447_rlhB.png

      就此请求完毕,一方发出了“发送文件”的请求,另一方“拒绝”了这个请求。

      这里有一个完整的数据传输协议,在官方的文档上是这样写的:

In order to enable seamless file transfer and appropriate fall-back mechanisms, implementations of this profile MUST support both SOCKS5 Bytestreams (XEP-0065) [4] and In-Band Bytestreams (XEP-0047) [5], to be preferred in that order. The associated namespaces are to be included as option values for the "stream-method" variable as shown in the examples below.


      上面的意思是说文件传输实际上是有协议XEP-0065和XEP-0047来进行的,而XEP-0096实际是传输IQ的消息协议,真正的传输数据并不 在次协议中,实现文件传输协议必须是full JID而且要求接收方在线。如果”to”(接收端), ”from”(发送端) 不是一个full JID,服务器就会发送error信息到”发送端”,说明服务器现在出现异常问题。

      现在我们来说说在传输消息的时候,该怎么具体组织消息:
      我们可以用IQ或者Message来发送数据。下面是我截取的文档中我觉得相当重要的部分:

Each chunk of data is contained in a <data/> element qualified by the 'http://jabber.org/protocol/ibb' namespace. The data element SHOULD be sent in an IQ stanza to enable proper tracking and throttling, but instead MAY be sent in a message stanza. The data to be sent, prior to base64-encoding and prior to any wrapping in XML, MUST NOT be larger than the 'block-size' determined in the bytestream negotiation.



      上面说啥呢,我英语也菜,但是能看懂一点2个关键点,一个是base64-encoding,block-size这个2个关键的单词,说明我们在遇到 大文件的情况下是进行分块发送的,每块的数据都是一定字节的,例如,我们发送数据1024字节,但是那个流怎么发送呢,都是二进制的。我们直接发送呢,数 据太大,不好整的,再则直接转String呢,那也是有问题的,因为String遇到’\o’就说明数据结束,会使数据漏掉很多。 文档中告诉我们,将发送的文件转换为base64之后再转为String类型,放入IQ或者Message数据格式中发送。关于base64的理论资料在 这里:http://zh.wikipedia.org/zh-cn/Base64=

      下面是一个数据实例:
22175447_GhIa.png

      参考的url地址:http://xmpp.org/extensions/xep-0096.html


Use of Message Stanzas
It is RECOMMENDED to use IQ stanzas when sending data packets. However, an application MAY use message stanzas instead. If message stanzas are used when sending data packets, the sender SHOULD also useAdvanced Message Processing (XEP-0079) [8] or some other stanza flow-control method. For proper tracking of delivery and processing errors related to data packets, the 'id' attribute SHOULD be used with message stanzas.

      上面的base64数据不一定用IQ发送,还可以用Message发送。只是在参数上有个改变一下就可以,哈哈。
      例子如下所示:

22175447_RqhI.png



      突然想起一件事情。。。在发送文件的时候,会有一个带<si >标签的数据段,这个数据段有id。这个id很重要,是必须要保存的。主要用在传输数据的时候,要是这个sid要是没有带上,那服务器就会返回错误信息给文件发送方。

      还有个小事情,我当初解析命名空间的时候,以为是一般属性,总是解析不出来。
最后发现有专门解析命名空间的东西,大家可以去google下。。。

      下面是进行文件传输的XEP-0096协议的完整xml例子:
22175447_soPt.png


数据协议都是人定的,哈哈

文件发送方:

22175447_2lBb.png



      我们可以对此IQ数据段解析,当发现file 标签的命名空间是http://jabber.org/protocol/si/profile/file-transfer的 时候 ,则表明这是“文件传输”消息请求。说明有人要传文件了。对于这个xml请求,我们在提取数据的时候必须提取<si>标签的ID。这个ID很 重要,是下面的sid传输数据的重要参数,也是判断是否是同一个数据流的依据。还有就是提取mine-type标签内容,这个是我们用来判断接收的是何种 文件,并以此判断创建该类型文件,把将要传来的数据写入这个文件,还有就是size标签内容,来检验我们接收的文件是否完整。

下面是一个完整的没有进行base64转换的数据请求:

文件接收方:
22175447_u92Z.png
      这里说明,我要接受的数据是什么协议,主要在file var这个参数:stream-method
<x submit>这个表明我要接受数据,你可以发给我了。


发送文件方:

22175447_4TIQ.png

      其实也要实现这个xml的,我不知道,当我接受数据之后,为什么要查询对方的机器名字,和一些基本数据,这可能是进行确认。

      接受方发出本机基本信息,主要有3个参数,category="client" name="Smack" type="pc"
22175448_WFed.png

      查询之后就开始要发数据了,哈哈。
      发出数据肯定要打开流,发送数据结束也要关闭流的,哈哈

发送方发送打开消息:

22175448_4XZb.png

      这个xml虽然很少,但是每个数据都很重要呢。Open的命名空间很熟悉那。其实这个就是前面刚开始接受数据file里的value,block- size说的是,我每次传数据都是以4096字节发送一个数据流。 这个sid就是发送方发送请求文件的那个<si>标签的id。都是相同的,同时还有一个重要的东西,stanza="iq"这个,相当的重 要,这个标签告诉对方,我要以IQ数据类型发送数据,这里也可以用message代替iq。前面我已经提及到。

下面的是message发送base64数据,如果stanza="message” 自己可以参照IQ发送base64数据。过程基本一样,就是iq变成message而已:

22175448_ePKt.png


接受方数据xml:
22175448_eW4h.png


22175448_6QcA.png

       上面的2个IQ是顺序发送的,不可逆,第一个是主要告诉对方。同时,那3个参数是上上面的一样的,要不是无法接收到额,还有一些对特征解释,说明传输的可以哪些流、
然后紧接着告诉对方,我可以解释数据了。

发送方开始发数据了,哈哈:

22175448_thXW.png

      这个data的value,是前面的数据块,4096字节base64加密数据。如果数据base64大于这个块。我们接到这个数据首先要base64解密之后,再写入刚才建立的文件中,
Sid是上面我们说的第一次si 标签的id。不能改变,更不能为null。也不要不设置,不然服务器就会返回错误信息。 Seq是从0开始的,如果还有流就会依次递增的,
如果接受处理完毕,就发送一个iq。说明接受完成  
说明一下哈,data里的数据被我删掉N多,我这主要是说明用。

接受方:

22175448_WqrK.png

      发一个一个4096字节base64加密数据。这个是源文件base64加密偏移的数据。

22175448_k7j0.png

      上面的seq变成1了,而sid依然没变。接受完成处理后,一样要回复一下,告诉他,可以继续传数据了。

      最后就是base64加密完成传输,要colse掉数据。


      发送方关闭流,这个sid依旧没有变,协议是这样规定的:
22175448_nrHi.png

      好吧,我知道你关闭流了。我们之间的文件传输完成了:
22175448_CQNb.png


写了几个小时分析,真的累。哎,下面贴出完整的流程xml
下面是整个对话阶段的xml数据:
A:发送方
B:接收方
A:
  1. <iq id="x36vr-54" to="zhufu@domian/android" from="saonian@domian/android" type="set">

  2.   <si xmlns="http://jabber.org/protocol/si" id="jsi_3326887048779603188" mime-type="image/png" profile="http://jabber.org/protocol/si/profile/file-transfer">

  3.     <file xmlns="http://jabber.org/protocol/si/profile/file-transfer" name="image_9T.png" size="5204">

  4.       <desc>Sending file</desc>

  5.     </file>

  6.     <feature xmlns="http://jabber.org/protocol/feature-neg">

  7.       <x xmlns="jabber:x:data" type="form">

  8.         <field var="stream-method" type="list-single">

  9.           <option>

  10.             <value>http://jabber.org/protocol/bytestreams</value>

  11.           </option>

  12.           <option>

  13.             <value>http://jabber.org/protocol/ibb</value>

  14.           </option>

  15.         </field>

  16.       </x>

  17.     </feature>

  18.   </si>

  19. </iq>

复制代码


B:
  1. <iq id="x36vr-54" to="saonian@domian/android" from="zhufu@domian/android" type="result">

  2.   <si xmlns="http://jabber.org/protocol/si">

  3.     <feature xmlns="http://jabber.org/protocol/feature-neg">

  4.       <x xmlns="jabber:x:data" type="submit">

  5.         <field var="stream-method">

  6.           <value>http://jabber.org/protocol/bytestreams</value>

  7.           <value>http://jabber.org/protocol/ibb</value>

  8.         </field>

  9.       </x>

  10.     </feature>

  11.   </si>

  12. </iq>

复制代码


A:
  1. <iq id="x36vr-55" to="zhufu@domian/android" type="get" from="saonian@domian/android">

  2.   <query xmlns="http://jabber.org/protocol/disco#info"></query>

  3. </iq>

复制代码


B:
  1. <iq id="x36vr-55" to="saonian@domian/android" type="result" from="zhufu@domian/android">

  2.   <query xmlns="http://jabber.org/protocol/disco#info">

  3.     <identity category="client" name="Smack" type="pc"/>

  4.     <feature var="http://www.xmpp.org/extensions/xep-0166.html#ns"/>

  5.     <feature var="urn:xmpp:tmp:jingle"/>

  6.   </query>

  7. </iq>

复制代码


A:
  1. <iq id="x36vr-56" to="zhufu@domian/android" type="set" from="saonian@domian/android">

  2.   <open xmlns="http://jabber.org/protocol/ibb" block-size="4096" sid="jsi_3326887048779603188" stanza="iq">

  3.   </open>

  4. </iq>

复制代码


B:
  1. <iq id="x36vr-55" to="saonian@domian/android" type="result" from="zhufu@domian/android">

  2.   <query xmlns="http://jabber.org/protocol/disco#info">

  3.     <identity category="client" name="Smack" type="pc"/>

  4.     <feature var="http://jabber.org/protocol/xhtml-im"/>

  5.     <feature var="http://jabber.org/protocol/muc"/>

  6.     <feature var="http://jabber.org/protocol/bytestreams"/>

  7.     <feature var="http://jabber.org/protocol/commands"/>

  8.     <feature var="http://jabber.org/protocol/si/profile/file-transfer"/>

  9.     <feature var="http://jabber.org/protocol/si"/>

  10.     <feature var="http://jabber.org/protocol/ibb"/>

  11.   </query>

  12. </iq>

复制代码


B:
  1. <iq id="x36vr-56" to="saonian@domian/android" from="zhufu@domian/android" type="result"/>

复制代码


A:
  1. <iq id="x36vr-57" to="zhufu@domian/android" type="set" from="saonian@domian/android">

  2.   <data xmlns="http://jabber.org/protocol/ibb" seq="0" sid="jsi_3326887048779603188">iVBORw0KGgoAAAANSUhEUgAAAEMAA

  3.   </data>

  4. </iq>

复制代码


B:
  1. <iq id="x36vr-57" to="saonian@domian/android" from="zhufu@domian/android" type="result"/>

复制代码


A:
  1. <iq id="x36vr-58" to="zhufu@domian/android" type="set" from="saonian@domian/android">

  2. <data xmlns="http://jabber.org/protocol/ibb" seq="1" sid="jsi_3326887048779603188">dcwRxoSYEFYOgxc0Qx2TSCNDSJZRTxKFgVmZiKFN</data>

  3. </iq>

复制代码


B:
  1. <iq id="x36vr-58" to="saonian@domian/android" from="zhufu@domian/android" type="result"/>

复制代码


A:
  1. <iq id="x36vr-59" to="zhufu@domian/android" type="set" from="saonian@domian/android">

  2. <close xmlns="http://jabber.org/protocol/ibb" sid="jsi_3326887048779603188"/>

  3. </iq>

复制代码


B:
  1. <iq id="x36vr-59" to="saonian@domian/android" from="zhufu@domian/android" type="result"/>

复制代码




转载于:https://my.oschina.net/vdroid/blog/202261

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/461657.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uboot源码——环境变量

以下内容源于朱有鹏嵌入式课程的学习&#xff0c;如有侵权&#xff0c;请告知删除。 参考资料&#xff1a;http://www.cnblogs.com/biaohc/p/6398515.html。 一、uboot的环境变量基础 1、环境变量的作用 在不改变源码、不用重新编译的情况下&#xff0c;可以通过设置环境变量…

Linq To Sql进阶系列 -目录导航

博客园CLR基础研究团队|CLR团队精品系列|C# 3.0专题 [Linq To Sql进阶系列] 目录导航 1 Linq To Sql进阶系列&#xff08;一&#xff09;-从映射讲起 本系列&#xff0c;或多或少&#xff0c;直接或间接依赖入门系列知识。但&#xff0c;依然追求独立成章。因本文作者水平有限&…

uboot源码——mmc驱动分析

以下内容源于朱有鹏《物联网大讲坛》课程的学习&#xff0c;以及博客http://www.cnblogs.com/biaohc/p/6409197.html的学习整理&#xff0c;如有侵权&#xff0c;请告知删除。 一、uboot与linux驱动 1、uboot是裸机程序 狭义的驱动的概念&#xff1a;操作系统中用来具体操控硬…

RDIFramework.NET(.NET快速开发框架) 答客户问(2014-02-23)

1、框架的部署安装&#xff0c;服务器端和客户端 答&#xff1a;开发版以上版本支持SOA模式&#xff0c;也即真正的面向服务端的模式&#xff0c;在实际使用过程中&#xff0c;可根据项目的实际需要&#xff0c;来选择性的进行部署&#xff08;直连模式或SOA模式&#xff09;&a…

I2C通信——I2C通信的基础介绍

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除 。 参考博客 SPI、I2C、UART&#xff08;即串口&#xff09;三种串行总线详解_天糊土的博客-CSDN博客_串口总线 s5pv210 I2C通信详解 - biaohc - 博客园 嵌入式常用技术概览之IIC(I2C)_C_XianRen的博…

IBM SOA[ESB,BPM,Portal等]基础架构图解

最近公司对众多的异构系统进行SOA化&#xff0c;产品选型为IBM的Websphere系列产品的WMB&#xff0c;BPM&#xff0c;Portal&#xff0c;LDAP等技术&#xff0c;根据具体的描述&#xff0c;连猜带蒙的画了个系统协作图&#xff0c;有不对的地方欢迎大家拍砖....谢谢。 SOA详细技…

css3图标悬停导航菜单

纯css3制作的图标悬停导航菜单&#xff0c;包含9中不同的悬停风格&#xff0c;干净大气。转载于:https://blog.51cto.com/jimanyu/1362823

I2C通信——S5PV210的I2C通信简单案例

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除。 参考内容 I2C子系统详解3——I2C总线驱动层代码分析_天糊土的博客-CSDN博客 一、S5PV210的I2C控制器 1、为什么需要控制器&#xff1f; 通信双方通过时序协调工作&#xff0c;但是时序比较复杂而…

POJ 2718

题意&#xff1a;给出最多10个数字&#xff0c;将它们划分为两个整数&#xff0c;求差异值最小的值&#xff08;除非只有一位数&#xff0c;否则不允许出现先导0&#xff09; 题解&#xff1a;很显然如果总共有n个数&#xff0c;必然有一个整数长n/2,另一个长n-n/2&#xff0c;…

HDUOJ---1879 继续畅通工程

继续畅通工程 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 11473 Accepted Submission(s): 5026 Problem Description省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通&#xff08;但不一…

动态载入树 (ASP+数据库)

ASPACCESS 在数据量达100万条记录下&#xff0c;载入速度仍然惊人.... // 网上转载. 忘了作者... : ) //********************** Index.asp ************************// 1<%LANGUAGE"VBSCRIPT"CODEPAGE"936"%>2<%OptionExplicit%>3<htm…

ADC——S5PV210的ADC的理论与操作

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除。 参考博客 s5pv210 AD转换 - biaohc - 博客园 一、ADC的相关概念 1、量程&#xff08;模拟量的输入范围&#xff09; ADC只能输入电压信号&#xff0c;其他种类的模拟信号要经过传感器的转换&#x…

【洛谷 2661】信息传递

题目描述 有 nn 个同学&#xff08;编号为 11 到 nn &#xff09;正在玩一个信息传递的游戏。在游戏里每人都有一个固定的信息传递对象&#xff0c;其中&#xff0c;编号为 ii 的同学的信息传递对象是编号为 T_iTi​ 的同学。 游戏开始时&#xff0c;每人都只知道自己的生日。之…

kernel移植——从三星官方内核开始移植

以下内容源于朱有鹏嵌入式课程的学习&#xff0c;如有侵权&#xff0c;请告知删除。 一、内核移植初体验 1、获取三星官方的内核源码包 三星SMDKV210开发板附带的光盘里有内核源码包&#xff1a;下载地址。 2、构建移植环境 &#xff08;1&#xff09;Windows下建立SI工程&…

Android中实时视频传输(摄像头实时视频传输)解决方案二

为什么80%的码农都做不了架构师&#xff1f;>>> 1、使用FFMpeg进行视频采集&#xff0c;使用Live555进行RTP传输&#xff0c;使用VideoView进行播放。 csdn提到&#xff1a;重载FrameSource&#xff0c;写一个服务类&#xff0c;可以从FrameSource的派生类读取帧数…

定时器——S5PV210定时器的理论与操作

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除。 一、定时器简介 1、定时器的含义 定时器作为SoC的外设&#xff0c;主要用来实现定时执行代码的功能&#xff0c;它相对SoC而言&#xff0c;就像闹钟相对于人的意义一样。定时器内部的计数器每隔一个…

uboot的移植——DM9000移植的理论基础

以下内容源于朱有鹏嵌入式课程的学习&#xff0c;如有侵权请告知删除。 一、网卡相关的基本知识 1、DM9000网卡芯片和SoC的连接 如上图所示&#xff0c;DM9000网卡芯片是通过SROM总线接口&#xff0c;或者说SROM控制器接入SoC的。下面分别介绍SROM控制器、DM9000网卡芯片的相关…

javascript深入浅出

第一章 数据类型 1&#xff0c;六种数据类型&#xff1a;原始类型&#xff08;number&#xff0c;string&#xff0c;boolean&#xff0c;null&#xff0c;undefined&#xff09; object对象&#xff08;Function Array Date&#xff09; 2&#xff0c;隐式转换&#xff1a;Na…

网络通信基础常识

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除。 1、网络通信属于进程间通信 进程间通信的一种方法是使用套接字socket&#xff0c;网络通信其实就是位于网络中不同主机上面的2个进程之间的通信。 2、网络通信的层次 网络通信的层次&#xff0c;即…

Android NDK工程创建与编译运行

首发地址&#xff1a;http://www.eoeandroid.com/thread-201993-1-1.html一、 工程创建1. 创建一个Android工程配置好开发环境并加载好对应版本sdk后&#xff0c;选择菜单File->New-> Project创建工程&#xff0c;工程类型选择Android Project&#xff0c;如下图所示&…