参考:http://gao-xianglong.iteye.com/blog/1944234
http://my.eoe.cn/808632/archive/6901.html
目前打算在项目中加上im及时通讯,openfire服务器是必须的还有asmack。
OpenFire是什么,以及它能做什么?或许这是许多开发人员最关心的一个话题。简单来说,OpenFire是一个采用纯Java语言编写(核心架构使用Mina构建)的开源RTC(Real-Time Communications,实时协作)服务器。它采用XMPP协议进行分布式通信,该协议的前身其实就是基于Jabber协议,只不过XMPP对其进行了部分扩展。说到底XMPP协议无非就是一个基于TCP/IP协议的扩展协议,它采用XML的方式进行数据传输,以此满足体系结构的中立。
当大家对OpenFire有一个大致的认识和了解后,我们再来探讨OpenFire能做什么。即时通信(IM,Instant Messenger)相信大家都应该听说过,比如我们常用的QQ、微信、米聊等等都是IM系统。那么这和OpenFire有什么关系呢?OpenFire既然是RTC服务器,自然开发人员就可以利用它构件一个具备高性能的即时通信服务器。OpenFire的性能如何呢?经过笔者和同事对其进行压力测试后发现,一台主流的8/16G服务器,在不集群(cluster)的情况下,使用多个Connection Manager(连接管理器)对OpenFire进行连接负载均衡,并对OpenFire做了一定的优化后,其完全可以承受住约10-20万左右的并发操作,如果session中不存储集合对象,抗住30-40万左右的高并发操作也不是没有可能。假设OpenFire无法满足你的应用需求时,开发人员完全可以对OpenFire的源码进行二次开发,使用插件的方式对其功能进行扩充,这一切都是OpenFire带给你的实惠。
当然,如果你仍然觉得OpenFire的性能还是无法满足于你的需求时,假设你具备扎实的NIO或者AIO编程经验,笔者完全支持并赞成你自己研发一个通信服务器,如果你做不到,那么请耐心并仔细的研究如何优化OpenFire的运行性能。要是想达到微信那种过亿用户连接数,千万级并发量,从理论上来说整体的系统架构必然非常复杂,这个时候架构师需要考虑的问题太多,比如:服务器之间如何集群?如何实现模块化部署?如何构建分布式缓存?海量数据如何处理?缓冲区如何构建?容灾或容错策略如何解决?带着这些疑问,笔者希望大家在工作或者是闲暇之余,耐心的思考下。
一、配置OpenFire服务器
所谓工欲善其事,必先利其器。我们在配置或二次开发OpenFire服务器之前,首先应该去官网下载OpenFire相关的一些构件和程序。大家可以登录站点进行下载http://www.igniterealtime.org/downloads/index.jsp,其中包括OpenFire服务器以及源码、Spark和Smack。Spark是利用Smack API进行与OpenFire服务器通信的客户端程序,而Smack就是提供给开发人员使用的基于XMPP协议的API。当成功下载好OpenFire服务器后,我们首先将其解压,然后在openfile/bin目录下找到openfire.exe,双击即可启动OpenFire服务器。
当成功启动OpenFire的服务器后,我们输入:http://127.0.0.1:9090进入OpenFire服务器的管理页面。OpenFire管理页面的端口为9090,缺省账号和密码都是admin。如果是第一次登录OpenFire服务器的管理页面,我们则需要配置一些初始信息,当成功配置好后,我们便可以完成登录
二、客户端和服务器通信
这里需要强调一点,我们在android上开发用的其实是移植版的类库asmack,而asmack现在在网上流传的版本是有BUG的,在传输文件的时候会报空指针异常。我在这个问题上也是耗时最多的,在网上找了许多网友修改过的版本,都不顶用,最后也是在eoe论坛中找到了靠谱的asmack
详见:http://www.eoeandroid.com/thread-186418-1-1.html
// 连接参数ConnectionConfiguration connConfig = new ConnectionConfiguration("192.168.0.1", 5222);connConfig.setReconnectionAllowed(true);connConfig.setSecurityMode(SecurityMode.disabled); // SecurityMode.required/disabledconnConfig.setSASLAuthenticationEnabled(false); // true/falseconnConfig.setCompressionEnabled(false);// 配置服务器XMPPConnection connection = new XMPPConnection(connConfig);try {
// 连接服务器connection.connect();// 用户登录connection.login("joe", "123456");// 向另一个用户发出聊天Chat chat = connection.getChatManager().createChat("admin@192.168.0.1/Spark 2.6.3", new MessageListener() {
// 消息回复函数@Overridepublic void processMessage(Chat arg0, Message arg1) {
System.out.println("Received message: " + arg1.getBody());try{
arg0.sendMessage("我已收到");} catch (XMPPException e){
e.printStackTrace();}}});// 发送聊天信息chat.sendMessage("Hello!");
// 连接参数ConnectionConfiguration connConfig = new ConnectionConfiguration("192.168.0.1", 5222);connConfig.setReconnectionAllowed(true);connConfig.setSecurityMode(SecurityMode.disabled); // SecurityMode.required/disabledconnConfig.setSASLAuthenticationEnabled(false); // true/falseconnConfig.setCompressionEnabled(false);// 配置服务器XMPPConnection connection = new XMPPConnection(connConfig);try { // 连接服务器connection.connect();// 用户登录connection.login("joe", "123456");// 准备发送的文件File file = new File(PATH);FileTransferManager transferManager = new FileTransferManager(connection);OutgoingFileTransfer outgoingFileTransfer = transferManager.createOutgoingFileTransfer("admin@192.168.0.1/Spark 2.6.3");// 发送文件outgoingFileTransfer.sendFile(file, file.getName());// 接收文件监听transferManager.addFileTransferListener(new FileTransferListener() { public void fileTransferRequest(FileTransferRequest request) { try { // 接收文件IncomingFileTransfer transfer = request.accept();// 接收文件存放的位置transfer.recieveFile(new File(PATH));} catch (Exception e) { Log.e("RecFile Ex In!",e.getMessage());}}});} catch (XMPPException e) { e.printStackTrace();}}如有问题请留言,转载注明出处