XMPP协议之Socket5 Bytestream文件传输 SOCK5流协商的建立一部分通过XMPP XML流,一部分通过一个独立的socket 实际的文件传输发生在创建的socket上。 第一步: [发送端] 发送SI(流协商)包A A: <iq type='set' id='gaim8215f9ef' [email=to=]to='test@dd.antkingdom.com/Exodus'[/email]> <si xmlns='http://jabber.org/protocol/si' id='gaim8215f9f0' profile='http://jabber.org/protocol/si/profile/file-transfer'> <file xmlns='http://jabber.org/protocol/si/profile/file-transfer' name='backup.txt' size='2043'/> <feature xmlns='http://jabber.org/protocol/feature-neg'> <x xmlns='jabber:x:data' type='form'><field var='stream-method' type='list-single'> <option><value>http://jabber.org/protocol/bytestreams</value></option> </field> </x> </feature> </si> </iq> [接收端] 接收A: 发送SI响应包B B: <iq id="gaim8215f9ef" to="[email=jjl@dd.antkingdom.com/Home]jjl@dd.antkingdom.com/Home[/email]" type="result"> <si id="gaim8215f9f0" xmlns="http://jabber.org/protocol/si"> <feature xmlns="http://jabber.org/protocol/feature-neg"> <x type="submit" xmlns="jabber:x:data"> <field var="stream-method"><value>http://jabber.org/protocol/bytestreams</value></field> </x> </feature> </si> </iq> 第二步: [发送端] 接收B 创建socket,绑定一个地址,并监听(记下IP与端口号),等待连接 构造出如下的bytestream包C,发送包C C: <iq type='set' id='gaim8215f9f1' [email=to=]to='test@dd.antkingdom.com/Exodus'[/email]> <query xmlns='http://jabber.org/protocol/bytestreams' sid='gaim8215f9f0'> <streamhost [email=jid=]jid='jjl@dd.antkingdom.com/Home'[/email] host='192.168.100.1' port='6642'/> </query> </iq> [接收端] 接收C: 创建一个socket, connect C包中指定的host与port 开始socket 5协商 socket 5协商完毕,发送bytestream响应包D D: <iq [email=from=]from='test@dd.antkingdom.com/Exodus'[/email] type='result' [email=to=]to='jjl@dd.antkingdom.com/Home'[/email] id='gaim8215f9f1'> <query xmlns='http://jabber.org/protocol/bytestreams' sid='gaim8215f9f0'> <streamhost-used [email=jid=]jid='jjl@dd.antkingdom.com/Home'/[/email]> </query> </iq> 第三步: [发送端] 接收D 开始文件传输 Socket 5协商过程 一、[接收端]发送5,1,0 二、[发送端]接收到5,1,0,发送5,0 三、[接收端]接收到5,0,发送5,1,0,3+digest长度+0+0 注:digest是通过sessionID, 流发起者,流接收者,通过哈希算法得到的一个字符串 四、[发送端]接收到5,1,0,3+digest长度+0+0,发送5,0,0,3+digest长度+0+0 五、socket 协商完毕,建立了P2P的连接,下面通过这个连接的socket就可以进行文件传输了。 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)的传输方式。
