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

本文介绍了IM系统中实现断线重连的机制,包括客户端通过定时检测连接状态,当发现断开时发起重连请求。服务端接收到请求后,更新用户和群组的Channel映射。该机制确保了在网络恢复后能及时恢复通信。

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 查询到群组的对话框集合,然后进行遍历更新即可。
-- ========== 🌐 Prosody XMPP Server 全局配置文件 ========== -- -- 目标:构建一个完整的页客服聊天系统 -- 功能:单聊、群聊、历史消息、文件传输、多设备同步 -- 文档: https://prosody.im/doc/configure -- 检查语法: sudo prosodyctl check config -- 启服务: sudo systemctl restart prosody -- -- 作者:Chat Assistant -- 时间:2025-04-05 -- ======================================================== ---------- 🔧 全局设置(必须在第一个 VirtualHost 之前) ---------- -- 👤 管理员账号(可选,用于接收注册通知等) admins = { } -- 📦 插件路径(如需加载第三方模块) plugin_paths = { "/var/lib/prosody/custom_plugins" } -- ⚙️ 启用的核心模块列表 modules_enabled = { -- === 基础功能 === "disco"; -- 服务发现 (XEP-0030) "roster"; -- 联系人列表 "saslauth"; -- 认证机制 "tls"; -- TLS 加密通信 "ping"; -- 心跳检测 "time"; -- 时间同步 "version"; -- 版本查询响应 -- === 安全与管理 === "admin_adhoc"; -- XMPP 内部管理命令 "admin_shell"; -- 命令行管理支持 (prosodyctl) "blocklist"; -- 黑名单屏蔽 "limits"; -- 连接速率限制 "mimicking"; -- 地址欺骗防护 "server_contact_info";-- 公开联系信息 "tombstones"; -- 防止已删除账号新注册 "watchregistrations"; -- 新用户注册提醒 "announce"; -- 广播通知所有在线用户 -- === 用户体验增强 === "bookmarks"; -- 书签同步(自动加入房间) "carbons"; -- 多设备消息同步 (XEP-0280) "dialback"; -- 服务器间身份验证 "motd"; -- 登录欢迎语 "private"; -- 私有数据存储 "pep"; -- 个人事件协议 "smacks"; -- 量控制与断线连 (XEP-0198) "vcard4"; -- 新版 vCard (XEP-0292) "vcard_legacy"; -- 兼容旧客户端的 vCard -- === 消息相关(关键!)=== "mam"; -- 消息归档 (XEP-0313) ✅ 查看历史 "default_archive"; -- 自动启用归档所有聊天 "offline"; -- 存储离线消息 ✅ 不丢消息 "register"; -- 开放用户注册 ✅ web 注册入口 -- === Web 接入支持 === "bosh"; -- BOSH HTTP 绑定 (长轮询) "websocket"; -- WebSocket 支持 (现代浏览器首选) "http_files"; -- 提供静态文件服务 (部署前端) -- === 工具与监控 === "account_activity"; -- 最后活动时间 "cloud_notify"; -- 送通知(移动端唤醒) "csi_simple"; -- 客户端节能优化 "uptime"; -- 查看运行时长 -- "http_openmetrics" -- Prometheus 指标导出(可选) } -- ❌ 可禁用的默认模块(通常不建议关闭) modules_disabled = { -- "c2s"; -- 危险!禁用客户端连接 -- "s2s"; -- 禁用服务器互联 } -- 🌐 HTTP 服务端口(BOSH + 静态文件) http_ports = { 5280 } -- 🔐 HTTPS 端口(用于 WSS 和加密资源) https_ports = { 5281 } -- ✅ 允许浏览器通过 BOSH 发送凭据(跨域登录必需) consider_bosh_secure = true -- ✅ 允许跨域请求(开发调试阶段开启) cross_domain_bosh = true cross_domain_websocket = true -- 🔐 认证方式:内部哈希密码存储 authentication = "internal_hashed" -- 💾 存储方式:使用 SQLite 数据库(荐) storage = "sql" sql = { driver = "SQLite3", database = "/var/lib/prosody/prosody.sqlite" } -- 🕒 消息归档保留时间(默认一周) archive_expires_after = "1w" -- 📄 日志输出配置 log = { info = "/var/log/prosody/prosody.log"; -- 正常日志 error = "/var/log/prosody/prosody.err"; -- 错误日志 debug = "/var/log/prosody/prosody_debug.log"; -- 调试日志(查看消息体) } -- 🔐 SSL/TLS 证书目录(Let's Encrypt 或手动放置) certificates = "/etc/pki/prosody/" -- 🏷️ PID 文件位置(Linux 系统) pidfile = "/run/prosody/prosody.pid" -- ⚖️ 带宽速率限制(防止滥用) limits = { c2s = { rate = "10kb/s"; -- 客户端输入限速 burst = "20kb"; -- 突发量允许 }; s2sin = { rate = "30kb/s"; }; } -- 🔐 强制服务器间安全认证 s2s_secure_auth = true -- 📊 是否收集统计信息(可选) -- statistics = "internal" ----------- 🏢 虚拟主机配置 ----------- VirtualHost "szrengjing.com" -- 主机启用状态 enabled = true -- SSL 证书(具体路径) ssl = { key = "/etc/pki/prosody/certs/szrengjing.com.key"; certificate = "/etc/pki/prosody/certs/szrengjing.com.crt"; } -- 主机级启用模块(覆盖全局) modules_enabled = { "roster"; "saslauth"; "tls"; "disco"; "ping"; "mam"; --消息归档 "offline"; -- ✅ 离线消息 "carbons"; -- ✅ 多端同步 "vcard4"; "bookmarks"; } ------ 🔧 组件配置(特殊功能子域名) ------ -- 📁 文件传输代理(NAT 穿透) Component "proxy.szrengjing.com" "proxy65" name = "文件传输代理" proxy65_address = "szrengjing.com" proxy65_port = 7777 -- 💬 多用户聊天室(群聊) Component "conference.szrengjing.com" "muc" name = "客服聊天室" persistent = true -- 房间持久化存在 max_occupants = 50 -- 最大人数 modules_enabled = { "muc_mam"; -- 群聊消息归档 } ---------- 🎯 模块专项配置 ---------- -- 📢 登录时显示提示语 motd_text = "欢迎登录客服系统!今日在线客服: 5人" -- 🛎️ 新用户注册时发送通知给管理员 watch_registrations = true registration_watchers = { "admin@szrengjing.com" } -- 💌 新用户注册后自动收到欢迎消息 welcome_message = "欢迎加入客服团队!请联系管理员获取培训资料。" -- 📞 公开服务器联系方式(客户端可查询) server_contact_info = { { category = "support", type = "email", value = "support@szrengjing.com" }, { category = "support", type = "xmpp", value = "support@szrengjing.com" } } ---------- 📁 包含额外配置文件 ---------- -- 自动加载 conf.d 下的所有 .cfg.lua 文件 Include "conf.d/*.cfg.lua" ---------- 🖥️ 静态文件服务配置 ---------- -- 提供页前端访问能力(例如你的 chat.html) http_paths = { files = "/www/wwwroot/szrengjing.com/js/chat" -- ✅ 指向你的前端目录 } ---------- ✅ 配置结束 ---------- -- 请勿在此处添加任何内容! -- 更多帮助: https://prosody.im/doc/configure 根据所需要的功能 生成配置完整版源文件 以在线客服 lm 功能进行完整配置 我们以经有了用户聊天窗口 最好是能步消息
最新发布
11-12
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值