jabber/XMPP文件传输的一些情况
1 jabber/XMPP文件传输的一些情况
大家知道,Jabber/XMPP是一种 XML流技术,解决的问题主要是即时消息和出席信息,XML流技术并不适用于大数据量的传输。
即时通信应用中,消息和出席信息的问题相对是比较简单和容易实现的,XMPP的在这方面的长处在于两点:
- 使用了XML流技术,XML天然的结构化和可扩展性特性,非常适合小数据量的字符信息交换。
- 更重要的,XMPP是一个公开的免费的标准,使得不同组织机构的即时消息可以互通,促使IM技术和应用从垄断走向平民化。
----- 但是即时通信的同样也离不开大数据量传输,来解决文件分享,多媒体应用等问题。为了解决这些问题,XEPs中提出了一些办法。在此之前,我们要区分什么是大数量传输,在XMPP\/XEP中,信息传输是所谓字符传输,而数据传输则是字节流传输(bytestreams)。
XEP中对于bytestreams的规定大致如下:
* XEP-0096: File Transfer 这是传输文件的统一接口,客户端之间用它来协商到底采用那种具体的传输方式,包括以下三种。
* XEP-0047: In-Band ByteStreams 带内字节流,这个协议实际上用于小数据量传输,只是它用的字节流传输,所以也顺便说一下。带内,也就是夹带在XML流中,通过XMPP服务器中转传输。具体用法是把数据用base64编码放在XML流中传给对方。这个办法不好,base64编码效率很低,而且所有数据必须由服务器中转。
* XEP-0066: Out of Band Data 带外字节流,带内不行就走带外,也就是不经过XMPP服务器。这个用法是在发起传输的客户端临时建立一个http服务(当然也可以是别的服务),把自己的IP和端口(通过XMPP消息)告诉接收方,让对方直接来下载。这个方法有一个问题,发送一方必须是公网IP,否则对方无法访问。 注:目前Pandion,Linq支持这个XEP。
* XEP-0065: SOCKS5 Bytestreams SOCKS5字节流,使用SOCKS5传输文件,有直连式和代理传输两种方式。发送方把预定的IP和端口(通过XMPP消息)告诉接收方。如果双方都在公网,采用SOCKS直接传输。如果任何一方在内网,经过SOCKS5代理服务器传输,发送方把代理服务器的IP和端口告诉给接收方。这里的SOCKS5代理服务器和通用的代理服务器稍有差别,因为它需要通过发送方提出的一个sessionID由XMPP服务器通知SOCKS5代理服务器把双方的SOCKS通道连通,也就是激活。 注:目前Psi,Linq支持这个XEP。
----- google的gtalk宣布采用XMPP标准之后,对于大数据量传输又采用了新的办法,也就是jingle。这个协议除了考虑文件传输,更多的考虑到了多媒体应用,不过总体来说它的思路和前述的方法相差不大,或者说是前述的XEP的扩展和优化。目前jingle在XEP中还处于试验状态,但是在gtalk中已经采用了jingle,而且gtalk完全不支持前述的XEPs。
大鳄都是这样了,仗着自己有钱有势......。
不过还是要说一下这个jingle,因为google毕竟把jingle公开了,这一点好过某些商业IM服务提供商,至少我们有机会去兼容它。
- XEP-0166: Jingle 这个协议的重点是考虑多媒体应用,当然也包括文件传输,它提出了一些多媒体应用的管理,如字节数据和描述数据分离以及多应用多会话的接口管理方面的建议,对于不同类型的应用,也有相应的jingle补充协议一一描述,如下表:
协议 | 描述 |
XEP-0166: Jingle | 负责协商和管理所有带外传输的会话 |
XEP-0167: Jingle Audio via RTP | 用RTP传输音频 |
XEP-0176: Jingle ICE Transport | 用ICE传输方法建立和管理数据连接 |
XEP-0177: Jingle Raw UDP Transport | 纯UDP传输 |
XEP-0180: Jingle Video via RTP | 用RTP传输视频 |
XEP-0181: Jingle DTMF | 对DTMF的简单支持 |
注1:ICE还是IETF正在开发的协议,尚未定型。
注2:DTMF也就是双音频拨号的电话,这里对DTMF的支持只是从XMPP的角度规定,可以管理类DTMF的会话,这样可以通过电话网关在XMPP客户端和普通电话之间用语音聊天。
这些是应用层面的东西,和这里的话题关系不大,另文再说。现在只说在实际字节传输的处理过程。 jingle的自己传输分为三类:
* 发送方在外网,采用类似oob(XEP-0066: Out of Band Data)的方式传输.
* 发送方在内网,采用STUN服务传输,也就是内网客户端的端口影射服务,把内网的IP和端口影射到STUN的IP和特定端口上,然后把这个外网的IP和端口告诉对方,然后还是采用类似oob(XEP-0066: Out of Band Data)的方式传输。
* 发送方在内网,但是没有可用的STUN服务器,采用relay server来转发,也就是这类似于proxy65(XEP-0065: SOCKS5 Bytestreams)的传输方式。
GTalk可以加上运行参数 /log verbose tstamp thread file 在桌面产生一个详细的 log 文件,以下是监听到的XML
<presence to='xxx' from='yyy'><status/><priority>0</priority>
<c xmlns="http://jabber.org/protocol/caps" node="http://www.google.com/xmpp/client/caps" ver="1.0.0.96" ext="share-v1 sidebar voice-v1"/>
<c xmlns='http://jabber.org/protocol/caps' ext='share-v1 voice-v1' ver='1.0.0.96' node='http://www.google.com/xmpp/client/caps'/>
<x xmlns='jabber:x:delay' stamp='20060817T11:43:04'/><x xmlns='vcard-temp:x:update'/></presence>
GTalk client 只有发现对方有 share-v1的情况下才允许文件传输,它似乎不关系 version 的版本.
if you init a file transfer they send:
<iq from='timyang' id='29' type='set' to='freetmp'>
<session xmlns='http://www.google.com/session' initiator='xxx'
id='866399561' type='initiate'>
<description xmlns='http://www.google.com/session/share'>
<manifest>
<file size='31124'>
<name>Export.csv</name>
</file>
</manifest>
<protocol>
<http><url
name='source-path'>/temporary/7a2e84d3cbf106cb68deed1cc418ca26/</url>
<url name='preview-path'>/temporary/de2185dda378483a65e0f8c4ad3e4327/</url>
</http>
</protocol>
</description>
<transport xmlns='http://www.google.com/transport/p2p'/>
</session>
</iq>
GTalk 新的文件传输没有使用已有的JEP, 而是利用了 Jingle 在连接方面的优势,Google 将会提交一个新的JEP
Connection/Session management: jingle
Reliability (change something udp-like into something tcp-like): pseudotcp
Transfer protocol: http
pseudotcp 现在还没有相关文档, 最早是在Picasa的 Hello IM/Photo-sharing程序里面为增加可靠性而使用,而且现在还没定型。
下一个google开源项目libjingle的版本将会看到文件传输的相关代码,但这些方法也还没有定型,将来极有可能会再次变化。