在openfire中添加消息队列,防止聊天信息丢失方法
来源:互联网 发布:android官方文档 知乎 编辑:程序博客网 时间:2024/06/08 03:11
在openfire中添加消息队列,防止聊天信息丢失方法
(2015-01-27 10:08:30)转载▼
标签:
it
分类: IM研究经过测试和研究openfire源码,发现当在断网情况下,大概一分钟左右服务器才断定客户端断开连接。而在这一分钟内发送的消息是没有存入离线消息表里的。致使消息丢失。当然这个时间是可以设置的,但是设置时长没有实际价值。因为不能让服务器实时判断客户端是否连接。于是添加了消息队列机制,处理消息丢失的问题。
//聊天消息放入消息队列 if(packet instanceof Message) { Message message = (Message)packet; Type type = message.getType(); if("chat".equals(type.name())||"groupchat".equals(type.name())){ Element request = message.getElement().element("request"); if(request!=null){ Message createCopy = message.createCopy(); messageQueue.offer(createCopy); //从队列中获取值发送 if(messageQueue.size()==1){ deliverMessage(createCopy); } return; } } } if (isClosed()) { backupDeliverer.deliver(queueMessage); } else { ByteBuffer buffer = ByteBuffer.allocate(4096); buffer.setAutoExpand(true); boolean errorDelivering = false; try { // OF-464: if the connection has been dropped, fail over to backupDeliverer (offline) if (!ioSession.isConnected()) { throw new IOException("Connection reset/closed by peer"); } XMLWriter xmlSerializer = new XMLWriter(new ByteBufferWriter(buffer, encoder.get()), new OutputFormat()); xmlSerializer.write(queueMessage.getElement()); xmlSerializer.flush(); if (flashClient) { buffer.put((byte) '\0'); } buffer.flip(); ioSession.write(buffer); } catch (Exception e) { Log.debug("Error delivering packet:\n" + queueMessage, e); errorDelivering = true; } if (errorDelivering) { close(); // Retry sending the packet again. Most probably if the packet is a // Message it will be stored offline backupDeliverer.deliver(queueMessage); } else { session.incrementServerPacketCount(); } } } if (closedSuccessfully) { //从消息队列中获取消息,插入到离线数据库 OfflineMessageStore instance = OfflineMessageStore.getInstance(); Iterator iterator = messageQueue.iterator(); while(iterator.hasNext()){ instance.addMessage(iterator.next()); } messageQueue.clear(); notifyCloseListeners(); } //判断是不是消息回执,如果是就获取消息队列进行操作 Element received = packet.getElement().element("received"); if(received!=null){ if(connection!=null && connection instanceof NIOConnection){ NIOConnection conn = (NIOConnection)connection; Queue messageQueue = conn.getMessageQueue(); String attributeValue = received.attributeValue("id"); Message peek = messageQueue.peek(); //如果相等就从队列清除 if(attributeValue.equals(peek.getID())){ messageQueue.poll(); //判断队列中是否还有message,如果有的话继续发送 if(messageQueue.size()!=0){ peek = messageQueue.peek(); conn.deliverMessage((peek)); } }else{ //继续从队列中发送message if(messageQueue.size()!=0){ peek = messageQueue.peek(); conn.deliverMessage(peek); } } } }
一下是具体实现:
一、在NIOConnection.java中的deliver方法中,添加消息队列。
所有的在线message都会经过这个 方法。
deliverMessage是一个发送message的方法,是根据发送的代码重构的,具体如下:
public void deliverMessage(Message queueMessage) throws UnauthorizedException{
二、在一分钟左右服务器确定客户端断开连接时,会触发close()方法,在close方法中将消息队列中的消息放入离线消息表。
三、在接收消息回执时,会操作消息队列。这里实在ClientStanzeHandler.java中,processMessage()方法中获取connection,这里需要说明一下,之所以在这里操作,是因为消息队列是存储在接收方的connection中,而消息回执接收的connection是自己的connection。从这里发送回执message的时候要获取的connection为接收方的connection,进而才能操作对方的消息队列。
代码如下:
至此,消息队列机制完成。经测试消息再也没有丢失。
内部还有一些细节,通过代码可以理解不在赘述。
阅读全文
0 0
- 在openfire中添加消息队列,防止聊天信息丢失方法
- openfire中添加好友发送验证消息
- RabbitMQ 防止消息丢失
- 三.防止消息丢失
- RabbitMQ防止消息丢失
- 基于openfire+smack开发Android即时聊天应用[三]-账号信息、添加好友、JID理解等
- 基于openfire+smack开发Android即时聊天应用[二]-账号信息、添加好友、JID理解等
- 基于openfire+smack开发Android即时聊天应用[三]-账号信息、添加好友、JID理解等
- Openfire MultiUserChat 多用户聊天 ---消息发送
- Openfire MultiUserChat 多用户聊天 ---消息发送
- openfire源码修改聊天消息发送内容
- openfire推送离线聊天信息的插件
- openfire推送离线聊天信息插件
- 在网页中添加QQ聊天按钮
- 在网页中添加QQ客服聊天
- 在网页中添加QQ聊天按钮
- asmack在openfire中发送自定义属性、节点的消息
- Flex中如何利用status属性,在Alert消息框上添加一个状态信息
- openfire 用户注册过程 服务器端
- 优化openfire服务器提升xmpp 效率的15个方法(原创)
- cocos加载3d精灵不显示,打印台无报错
- 开发创建XMPP“发布订阅”扩展(xmpp pubsub extend)
- openfire 服务端讯息回执添加和响应
- 在openfire中添加消息队列,防止聊天信息丢失方法
- 高德API调研
- openfire连接登陆优化方案
- 简明教程-linux 之 7z文件解压缩
- 使用movielens-100k测试UserBasedCF与ItemBasedCF并可视化结果
- 基于XMPP协议的消息推送的客户端和服务器端
- 从PAXOS到ZOOKEEPER分布式一致性原理与实践--2PC(Two-Phase Commit)
- Lua运行环境搭建
- 工具