gloox收发文件

今天说一下关于通过gloox收发文件的使用方法。在XMPP协议中收发文件并不是作为XMPP协议标准进行发布的,而是有一个扩展协议,在这个扩展协议里面描述了进行文件收发时的协议要求,当然gloox库里面已经实现了这个扩展协议,也提供了调用API,所以,我们是可以直接用这个gloox开发库进行文件收发的实现的。

在这个gloox文章中,很少以直接贴源代码的方式进行说明,主要原因是那样会增加文章的长度,并且我觉得也不一定能把握得了重点,更何况一些头文件的描述是需要加入的(假如以贴代码的方式),这样的话,就需要解释每个头文件是用来干什么的,这样一来,更增加了文章的复杂度,不可取,所以需要使用者结合Gloox开发包中的example文件夹下面的示例,再结合文章会更加理解透彻一些。同时example目录里面的示例只是一个简单的使用方式,并不能在实际的项目应用中提供支持,所以更加需要去理解其中的一些方法,那样,就可以很好的利用这个开发库了。在我的实际项目的使用中,对Gloox进行了进一步的封装,主要原因是让使用者不用去考虑那么多的头文件,接口等,如果有可能,我在后面可以把我的实际中的封装库拿出来共享,使用起来也是非常简单的。

好了,言归正转,下面说一下如何实现向远端JID发送文件,同时说一下关于文件路径中文乱码的问题。

向远端发送文件有个前提条件是,发文件双方得在一个组内,不然两个陌生的JID之间是不可能发文件的(这个在XMPP的相关协议中并未提及),另外远端的JID得需要是一个完整的标识,包括“/”后面的资源名也得用上,完整的示例如:hurkhurk@example.net/glooxsendfile。同时有这样的情形是完全存在的,你可能同时给很多个JID发送多个文件,甚至给同一个JID发送多个文件,那么从策略上来说(与gloox无关)应该怎么做呢?我个人觉得有两种方式可以考虑,一是只要发一个文件,不管给谁发,就开一个线程,二是只开一个线程,用这个线程专门用来进行文件发送,在我的实际使用中采用了第二种方式,我对文件的收和发用了两个线程,一个专用于接收文件的,另一个专用于发送文件的,当接收文件或者发送文件的数量为0时,则停止文件的收发。关于这方面,网上倒是有一个封装得比较好的代码,可以参考一下,地址是:http://icalk.googlecode.com/svn-history/r81/trunk/src/ ,里面有个TalkFT.hTalkFT.cpp。里面对通过gloox的封装和使用进行了一个比较好的方式进行封装。里面有一些关键点需要注意,一是在它的里面的使用中,似乎与gloox还是有些区别的,这个要以gloox里面的example里的为准。另外,那里面也有一些BUG的,比如对steam流的管理有些问题,并没有对其进行释放等,没有本地取消文件的收发方法(当然实现起来并不难)。当然总体来说,里面体现的想法是值得可取的,我也是因为看了里面的代码,对我的封装有了莫大的帮助。

由于要将gloox用来收发文件说起来非常麻烦,所以我在这里,只说一些比较关键和重要的地方,其余的可以参考example下面和前面提到的那个地方去下载TalkFT类来看看,我觉得应该没有大问题的。

下面是需要注意的地方:

任何一次发文件还是收文件,都会有一个对应的SID标识的,开发人员需要做的是要将这个SID进行管理,因为使用者可能随时会取消传输或者接收中的文件,而使用都到底是取消了哪个文件传输,则是由其对应的SID来区别的,gloox后台则可以根据该SID找到对应的流通道,将其关闭即可。在实际使用中,通常需要将SID与显示文件传输进度的进度条进行关联,当使用者取消文件传输时,则可以通过关联关系找到取消文件传输中对应的SID。那么这个SID在哪里呢?如果是你要发送文件,则调用const std::string requestFT( const JID& to, const std::string& name, long size,

                                   const std::string& hash = "", const std::string& desc = "",

                                   const std::string& date = "", const std::string& mimetype = "" );函数即可,该函数的返回值则为SID。该函数在类SIProfileFT中。如果要接收文件,则在SIProfileFTHandler类中的virtual void handleFTRequest( const JID& from, const std::string& id, const std::string& sid,

                                    const std::string& name, long size, const std::string& hash,

                                    const std::string& date, const std::string& mimetype,

                                    const std::string& desc, int stypes, long offset, long length ) = 0;的实现中,第三个参数即是对应的SID

第二点:在gloox库中如果你自己是发送文件方,则需要你自己做文件传输服务器,需要自己开一个端口,这就是在程序中经常看见的这样一句话:m_server =

              new SOCKS5BytestreamServer(m_client->logInstance(), 6666);的意思,如果你是做为接收文件方,则不需要开这样一个端口,做服务器。你只需要连接到代理服务器的端口就可以了,这就是在示例程序中经常看见的这样一句话:m_ft->addStreamHost( JID("proxy."+m_client->server()), m_client->server(), 7777 );

它实际上指向了对应的IM服务器的7777端口。那么下面再具体说一下关于XMPP协议中的文件传输问题与gloox的使用问题。在XMPP的文件传输扩展协议中(不属于XMPP协议标准协议),文件传输有两种方式,一是点对点的,另一种是用代理服务器的方式,点对点的方式看起来似乎很好,但是在实际中有一定的缺陷,因为如果收发文件双方处于防火墙后面,则点对点的方式是不能进行的(虽然你可以通过打洞方式穿越防火墙,但是象对称模型的NAT似乎不能穿越),所以一般情况下用第二种方式,即代理,而这个代理通常是在外网中的,所以通过发送文件方和接收文件方都去连接代理,通过代理获得数据是比较可取的。而gloox库中就是使用的代理。所以你需要把对应的文件代理服务器加入至代码中。不过有一点我不是很明白,按XMPP协议描述来说,文件代理服务器进行文件的收发工作,但是为什么用Gloox的接收端需要自己开端口作为服务器,让代理服务器来连呢?当然收文件是没有什么问题的,总是从文件代理服务器上下载文件。

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值