xmpp 文件传输协议:

  1. XEP-0096: SI File Transfer:文件传输流初始化协议
  2. XEP-0065: SOCKS5 Bytestreams:带外socks5代理字节流传输协议
  3. XEP-0047: In-Band Bytestreams:带内字节流传输协议
  4. XEP-0066: Out of Band Data:带外数据传输协议
  5. XEP-0030: Service Discovery:服务发现协议
  • XEP-0096:文件传输流初始化协议。支持断点续传。当file元素包含range无素时,range包含offset、length两个属性,可以指出要传送的数据位于文件的什么位置。
  • xep-0047:是把数据进行base64编码后,放到iq消息中转发。这个适用于小数据传输。
  • xep-0066:带外数据传输,是从发送端拉取。这个需要发送端位于公网。
  • xep-0065:带外数据传输,如果发送端位于公网,则接收端直接连接发送端拉取数据。如果双方都位于内网,则双方连接代理服务器,通过代理服务器转发数据。
  • XEP-0030:服务发现协议,这里用来发现代理服务。
xep-0065 协议:

直接连接流程:

Requester                         Target
| |
| Send S5B initiation request |
| -----------------------------> |
| |
| Open TCP socket |
| <_____________________________ |
| |
| Request SOCKS5 connection |
| <\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ |
| |
| Acknowledge SOCKS5 connection |
| /////////////////////////////> |
| |
| Send S5B acceptance |
| <----------------------------- |
| |
| Exchange data over S5B |
| <============================> |
| |

间接连接流程:

Requester                         Proxy                            Target
| | |
| Send S5B initiation request |
| --------------------------------------------------------------> |
| | |
| | Open TCP socket |
| | <_____________________________ |
| | |
| | Request SOCKS 5 connection |
| | <\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ |
| | |
| | Acknowledge SOCKS 5 connection |
| | /////////////////////////////> |
| | |
| Send S5B acceptance |
| <-------------------------------------------------------------- |
| | |
| Open TCP socket | |
| _____________________________> | |
| | |
| Request SOCKS 5 connection | |
| /////////////////////////////> | |
| | |
| Acknowledge SOCKS 5 connection | |
| <\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ | |
| | |
| Request activation | |
| -----------------------------> | |
| | |
| Acknowledge activation | |
| <----------------------------- | |
| | |
| Exchange data over S5B |
| <=============================================================> |
| | |

qxmpp 文件传输:

qxmpp中的文件传输实现了:

  • XEP-0096: SI File Transfer
  • XEP-0047: In-Band Bytestreams
  • XEP-0065: SOCKS5 Bytestreams
  • XEP-0030: Service Discovery

QXmppTransferManager:实现XEP-0096、XEP-0047、XEP-0065
QXmppDiscoveryManager:实现 XEP-0030

实例:
  • 流初始化过程(XEP-0096):
    发送端:

        <iq id="qxmpp73" to="c@rabbitim.com/QXmpp" type="set">
            <si xmlns="http://jabber.org/protocol/si" 
                id="MsVtTkTuwqKQhMBxUsuM66qLgEG9r4Cr" 
                profile="http://jabber.org/protocol/si/profile/file-transfer">
                <file xmlns="http://jabber.org/protocol/si/profile/file-transfer" 
                    date="2009-07-14T04:52:25.650Z" 
                    hash="076e3caed758a1c18c91a0e9cae3368f" 
                    name="Chrysanthemum.jpg" 
                    size="879394"/>
                <feature xmlns="http://jabber.org/protocol/feature-neg">
                    <x xmlns="jabber:x:data" type="form">
                        <field type="list-single" var="stream-method">
                            <option><value>http://jabber.org/protocol/ibb</value></option>
                            <option><value>http://jabber.org/protocol/bytestreams</value></option>
                        </field>
                    </x>
                </feature>
            </si>
        </iq>
                                            

目标端:

<iq id="qxmpp73" to="b@rabbitim.com/QXmpp" type="result" from="c@rabbitim.com/QXmpp">
<si xmlns="http://jabber.org/protocol/si"
profile="http://jabber.org/protocol/si/profile/file-transfer">
<feature xmlns="http://jabber.org/protocol/feature-neg">
<x xmlns="jabber:x:data" type="submit">
<field type="list-single" var="stream-method">
<value>http://jabber.org/protocol/bytestreams</value>
</field>
</x>
</feature>
</si>
</iq>
  • 查询代理过程(XEP-0030):
    发送端:

服务器回复信息,告知可用的代理:

<iq type="result" id="qxmpp74" to="b@rabbitim.com/QXmpp">
<query xmlns="http://jabber.org/protocol/disco#items">
<item jid="proxy.rabbitim.com" name="Socks 5 Bytestreams Proxy"/>
<item jid="pubsub.rabbitim.com" name="Publish-Subscribe service"/>
<item jid="conference.rabbitim.com" name="公共房间"/>
<item jid="search.rabbitim.com" name="User Search"/>
</query>
</iq>

这个代理查询过程,qxmpp有单独的类实现,查询到的结果用 QXmppTransferManager::setProxy 告知 QXmppTransferManager

  • 得到代理配置过程: 这里选择name=“Socks 5 Bytestreams Proxy”的代理,初始方给这个代理发送信息获取代理连接信息
    发送端:

代理:

<iq type="result" id="qxmpp75" from="proxy.rabbitim.com" to="b@rabbitim.com/QXmpp">
<query xmlns="http://jabber.org/protocol/bytestreams">
<streamhost jid="proxy.rabbitim.com" host="182.254.185.29" port="7777"/>
</query>
</iq>
  • 连接代理过程(XEP-0065):
    发送端:

这里的 streamhost 是有顺序关系的。主机地址放在最前,代理放在最后。目标端会接这个顺序去连接。如果前面的可以连接上,就不在做后面的。 这个可以保证先直接连接,只有在直接连接不成功后,才连接代理,进行转发。

目标端: 目标端按上一步发过来的信息,按照streamhost的顺序连接。如果成功,则返回下面信息通知发送端。

<iq id="qxmpp77" to="b@rabbitim.com/QXmpp" type="result" from="c@rabbitim.com/QXmpp">
<query xmlns="http://jabber.org/protocol/bytestreams"
sid="MsVtTkTuwqKQhMBxUsuM66qLgEG9r4Cr" mode="tcp">
<streamhost-used jid="proxy.rabbitim.com"/>
</query>
</iq>

代理:

<iq type="result" id="qxmpp79" from="proxy.rabbitim.com" to="b@rabbitim.com/QXmpp"/>

OpenFire 中的文件传输设置:

文件代理有下面几个设置:

  • xmpp.filetransfer.enabled = true
  • xmpp.proxy.service=proxy
  • xmpp.proxy.enabled=ture
  • xmpp.proxy.port=7777
  • xmpp.proxy.externalip=127.0.0.1

上面这几个后面的值是默认值。前面四个用默认值就可以了,但最后一个需要设置为代理服务器的外网地址。 而代理服务器的jid:

    proxyServiceName = JiveGlobals.getProperty("xmpp.proxy.service", "proxy");
/**
* Returns the fully-qualifed domain name of this chat service.
* The domain is composed by the service name and the
* name of the XMPP server where the service is running.
*
* @return the file transfer server domain (service name + host name).
*/
public String getServiceDomain() {
return proxyServiceName + "." + XMPPServer.getInstance().getServerInfo().getXMPPDomain();
} public JID getAddress() {
return new JID(null, getServiceDomain(), null);
}

所以,文件代理服务器的jid为下面两个配置值的组合: xmpp.proxy.service、xmpp.domain

文件传输的代码位于源码目录: src/java/org/jivesoftware/openfire/filetransfer

总结:
  • 配置域名:xmpp.domain为rabbitim.com
  • 配置扩展IP:xmpp.proxy.externalip为文件代理服务器的外网ip
  • 客户端程序查询到代理后,在发送文件前,要调用 QXmppTransferManager::setProxy 设置代理。 本程序为:m_TransferManager.setProxy("proxy.rabbitim.com");

xmpp发送文件的更多相关文章

  1. ios xmpp 发送语音图片解决方案

    ios xmpp 发送语音,图片解决方案,有需要的朋友可以参考下. 目前做IM多是用的xmpp. 因为项目需求需要实现语音和图片的发送. 发送语音图片有三种方法. 1,xmpp smack.文件传输方 ...

  2. win7系统下的飞秋发送文件失败问题

    飞秋发送文件失败这个问题大多数是由防火墙引起的1.检查windows自带的防火墙设置,在左侧的"允许程序通过windows防火墙"查看飞秋是否存在,不存在则增加之,公网.专网都勾选 ...

  3. 利用Socket远程发送文件

    思想: 1.注意使用两个通道,一个普通对象通信通道,另一个纯净的文件字节流通道 2.利用通信通道发送文件请求,新建字节流通道,开始发送文件

  4. [转]C#网络编程(订立协议和发送文件) - Part.4

    本文转自:http://www.tracefact.net/CSharp-Programming/Network-Programming-Part4.aspx 源码下载:http://www.trac ...

  5. android开发,socket发送文件,read阻塞,得不到文件尾-1

    这是我的接收文件代码:开始可以读取到-1,但是现在又读取不到了,所以才加上红色字解决的(注释的代码) File file = new File(mfilePath,"chetou." ...

  6. tengine lua 开源一 调用内部接口高效发送文件

    tengine  lua 开源一 调用内部接口高效发送文件 开源自己封装的sendfile 模块,可以高效的通过lua发送文件 源码地址:https://github.com/weinyzhou/Lu ...

  7. ASP.NET MVC:通过 FileResult 向 浏览器 发送文件

    在 Controller 中我们可以使用 FileResult 向客户端发送文件. FileResult FileResult 是一个抽象类,继承自 ActionResult.在 System.Web ...

  8. socket(TCP)发送文件

    一:由于在上一个随笔的基础之上拓展的所以直接上代码,客户端: using System; using System.Collections.Generic; using System.Componen ...

  9. C#_Socket网络编程实现的简单局域网内即时聊天,发送文件,抖动窗口。

    最近接触了C#Socket网络编程,试着做了试试(*^__^*) 实现多个客户端和服务端互相发送消息 发送文件抖动窗口功能 服务端: using System; using System.Collec ...

随机推荐

  1. Extjs通过structs2生成树结构

    Extjs为我们提供了强大的树的生成方式,我们不必通过原始的js去生成树形结构.在这里我做了一个简单的树结构生成.代码如下,同时在后台使用了fastjson-1.1.15.jar的jar包生成json ...

  2. Shuffle'm Up

    poj3087:http://poj.org/problem?id=3087 题意:题意简化之后的就是:给你两个长度均为c的字符串s1,s2,然后给你一个2*c的串ss,现在每次从s2,中取一个,然后 ...

  3. hdu 5072 Coprime

    http://acm.hdu.edu.cn/showproblem.php?pid=5072 题意:给出 n 个互不相同的数,求满足以下条件的三元无序组的个数:要么两两互质要么两两不互质. 思路:根据 ...

  4. 一句话改变TGraphicControl控件的left坐标的前世今生

    稍微用脑子想了一下,图形控件没有句柄,因此先把自己的坐标改一改,然后只要把父控件的某些区域Invalidate一下就可以了,WM_PAINT消息一来,父控件就会重绘所有子图形控件,就达到了相应的效果. ...

  5. 14.5.2.3 Consistent Nonlocking Reads 一致性非锁定读

    14.5.2.3 Consistent Nonlocking Reads 一致性非锁定读 一致性读意味着 InnoDB 使用多版本来实现一个查询数据库的快照在某个时间点. 查看看到的事务做出的改变被提 ...

  6. POJ- 2104 hdu 2665 (区间第k小 可持久化线段树)

    可持久化线段树 也叫函数式线段树也叫主席树,其主要思想是充分利用历史信息,共用空间 http://blog.sina.com.cn/s/blog_4a0c4e5d0101c8fr.html 这个博客总 ...

  7. 【模拟】NEERC15 A Adjustment Office (2015-2016 ACM-ICPC)(Codeforces GYM 100851)

    题目链接: http://codeforces.com/gym/100851 题目大意: 一个N*N的矩阵A,Ai,j=i+j,Q次操作,每次分两种,R r取出第r行还未被取的所有数,并输出和.C c ...

  8. Python中的迭代器和生成器

    本文以实例详解了python的迭代器与生成器,具体如下所示: 1. 迭代器概述: 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后 ...

  9. M - 昂贵的聘礼 - poj1062

    Description 年轻的探险家来到了一个印第安部落里.在那里他和酋长的女儿相爱了,于是便向酋长去求亲.酋长要他用10000个金币作为聘礼才答应把女儿嫁给他.探险家拿不出这么多金币,便请求酋长降低 ...

  10. IFTT-意大利金融交易税

    港交所公告,IFTT目前适用于Prada股份及其4只权证,所有于今年3月1日或之后买入Prada的投资者均要缴付IFTT.就股份而言,IFTT税率为交易价值的0.22%(2014年1月1日起将降至0. ...