转载

iOS客户端 Openfire服务 利用XEP-0065和XEP-0096 做out-of-band bytestream文件传输

Openfire服务可以做文件传输方法可供选择有:

  • XEP-0047: in-band bytestreams:带内字节流传输协议  base64编码后放入iq消息,同普通文字消息,编解码需耗点资源效率一般,适用于较小文件;
  • XEP-0096: SI File Transfer:文件传输流初始化协议  
    • 文档中提到可自行选择开发支持断点续传。当file元素包含range无素时,range包含offset、length两个属性,可以指出要传送的数据位于文件的什么位置。
  • XEP-0065: SOCKS5 Bytestreams:带外socks5代理字节流传输协议
    • 文档中提到 如果发送端位于公网,则接收端直接连接发送端拉取数据。如果双方都位于内网,则双方连接代理服务器,通过代理服务器转发数据。
    • 两种应用场景原文:
      1. A direct connection in which the StreamHost is the Requester, as described under  Direct Connection
      2. A mediated connection in which the StreamHost is a Proxy, as described under  Mediated Connection
  • XEP-0066: Out of Band Data:带外数据传输协议
    具体看协议文档,没搞过;XEP-0096中提到XEP-0066的drawbacks,原文:
    • It is not reliable.
    • It does not work when one of the parties is behind a firewall.
    • It provides limited metadata about files to be exchanged
  • 还有一种,自建个文件服务器,发送方发送文件到文件服务器,上传成功后生成相应的缩略图(如果是图片文件的话)推送完成的消息给接收方,接收方收到消息后,去下载相应的文件,比较好理解,但我猜想每次比上述的方式多了次 磁盘IO;项目进度急得话,也是可以选用,可后续优化嘛。

我选的是XEP-0096和XEP-0065 :

XEP-0096对应的iOS版本文件 地址 ,XEP-0065 iOS 版本也可用上述地址的版本

初始化XMPPStream时需要注意:

XMPPJID *jid = [XMPPJID jidWithString:[NSString stringWithFormat:@"%@@%@", account, XMPPDomain]];     XMPPJID *jidWithResource = [jid jidWithNewResource:@"ios"];     [self.xmppStream setMyJID:jidWithResource];

普通JID格式如:account@domain (形如 hanmeimei@test)

第二行带上resource,不带我的程序报错:

<error code="503" type="cancel"><service-unavailable xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/></error>

应该是两端的resource不一致

初始化 XMPPSIFileTransfer相应代码:

NSString *sessionId = [_xmppStream generateUUID];     _sifiletransfer = [[XMPPSIFileTransfer alloc] init];     _sifiletransfer.sid = sessionId;     [_sifiletransfer addDelegate:self delegateQueue:dispatch_get_main_queue()];     [_sifiletransfer activate:_xmppStream];

发送文件:

- (void)sendImageMessage:(NSData *)imageData toAccount:(NSString *)account{     XMPPJID *jid = [XMPPJID jidWithString:[NSString stringWithFormat:@"%@@%@/%@", account, XMPPDomain, [[_xmppStream myJID] resource]]];     [_sifiletransfer initiateFileTransferTo:jid withData:imageData]; }

其中文件接收方的JID完整格式:account@domain/resource (形如 hanmeimei@test/ios)

发送完成后在 XMPPSIFileTransfer.h中的

@protocol XMPPSIFileTransferDelegate <NSObject> @required - (void)receivedImage:(NSData*)image from:(XMPPJID*)from; @end

可在你自己的文件中实现该方法接受文件

至此,我在内网可以通过此方式传输文件,Mac下得openfire服务,可选用源码或dmg方式 均可;

后来测试一端内网,一端外网出现错误,提示为:

<error code="404" type="cancel"><item-not-found xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/></error>

openfire后台配置:

注意xmpp.proxy.externalip 填写你测试服务器的外网地址

iOS客户端 Openfire服务 利用XEP-0065和XEP-0096 做out-of-band bytestream文件传输

路由器的7777端口也要映射到外网,如图:

iOS客户端 Openfire服务 利用XEP-0065和XEP-0096 做out-of-band bytestream文件传输

至此,内外网两端发送文件测试也通过。

希望能帮到您。

正文到此结束
Loading...