IM系统第六章 -- 断线重连恢复通信

IM系统第六章 – 断线重连恢复通信

你是如何实现该功能的?

断线重连该机制在通信中是一种很重要的机制,假如没有该机制,无法及时在恢复网络的时候接收到对方发来的消息,需要退出登录重新连接才能接收的到;为了解决这个情况,”断线重连“机制就应运而生了。

那这种机制你如何实现?利用在客户端中 定时检测连接状态的方式,来判断是否保持良好的链接,如果断开就进行重连恢复通信。

下图为实现该逻辑流程图(参考 小傅哥

img

实现功能所需的处理:

  1. 自定义协议;
  2. 服务端断线重连处理;
  3. 客户端实现心跳机制处理;

自定义协议:ReconnectRequest

// 断线重连请求  协议
public class ReconnectRequest extends Packet {
    private String useId; // 发起重连的用户Id
    public ReconnectRequest(String userId) {
        this.userId = userId;
    }
    public String getUserId() {
        return userId;
    }
    public void setUserId(String userId) {
        this.userId = userId;
    }
}

自定义完协议后,客户端的Application中设定 定时检测连接状态 机制;

public class Application extends javafx.application.Application {
    // 默认线程池
    private static final ExecutorService executorService = Executors.newFixedThreadPool(2);
    private final ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
    // Channel状态定时巡检,3s后每5s执行一次连接检测
    scheduledExecutorService.scheduleAtFixedRate(() -> {
        while(!nettyClient.isActive()) {
            try{
                System.out.println("通信管道巡检:断线重连[begin]");
                // 重新提交 nettyClient任务到executorService线程池中
                Channel freshChennel = executorService.submit(nettyClient).get();
                // 如果缓存中的userId为空,则跳过
                if(null == CacheUtil.userId) continue;
                // 否则将userId作为 重连请求协议的参数 传送过去
                freshChannel.writeAndFlush(new ReconnectRequest(CacheUtil.userId));
            }catch(Exception e) {
                System.out.println("通信管道巡检:断线重连[error]");
            }
        }
    } 3,5,TimeUnit.SECONDS);
}

服务端的主要任务:发生断线重连后,客户端发来 重连请求协议,利用这个协议的userId 结合SocketUtil 工具类来将原有的用户管道删除,然后增添新的现在参数的channel(添加用户channel的操作);从数据库中查到该用户的 群组的对话框集合,然后进行遍历更新。

public class ReconnectHandler extends MyBizHandler<ReconnectRequest> {
    @Override
    public void channelRead(Channel channel, ReconnectRequest msg) {
        // 添加个人channel[删除原有的channel,增添新的channel与用户id的映射]
        SocketChannelUtil.removeUserChannelByUserId(msg.getUserId());
        SocketChannelUtil.addChannel(msg.getUserId(), channel);
        
        // 添加群组channel[通过查询用户的 对话群组,然后遍历来更新]
        List<String> groupsList = userService.queryTalkBoxGroupsIdList(msg.getUserId());
        for(String groupId : groupsList) {
            SocketChannelUtil.addChannelGroup(groupId,channel);
        }
    }
}

总结

分三步:

  1. 自定义 断线重连协议;
  2. 客户端中Application 要实现 定时检测连接状态 机制,每5s就进行一次心跳机制;如果CacheUtil.userId 不为空,就证明该用户已经断开连接,需要发 重连请求 协议过去给服务端;
  3. 服务端中,主要是对用户 原有的channel进行删除 和 新的channel进行了增添,群组就从数据库中 根据用户的id 查询到群组的对话框集合,然后进行遍历更新即可。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值