java-netty客户端断线重启
背景
经常会遇到netty客户端,因为网络等多种原因而断线,需要自动重连
核心
就是对连接服务端成功后,对ChannelFuture进行监听,核心代码如下
f = b.connect("127.0.0.1", 10004).sync(); // (5)f.addListener(new ChannelFutureListener() {@Overridepublic void operationComplete(ChannelFuture channelFuture) throws Exception {if(!channelFuture.isSuccess()){System.out.println("重试");channelFuture.channel().eventLoop().schedule(new Runnable() {@Overridepublic void run() {doReconnect();}},3,TimeUnit.SECONDS);}else{}}});
具体代码
nettyClient
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import java.util.Random;
import java.util.concurrent.TimeUnit;public class nettyClient {private static ChannelFuture f;static EventLoopGroup workerGroup;static Bootstrap b;static ChannelFutureListener channelFutureListener=null;static NettyClientHandlerInner nettyClientHandlerInner = new NettyClientHandlerInner();public static void main(String[] args) throws Exception {new Thread(new Runnable() {@Overridepublic void run() {while (true) {try {Thread.sleep(2000);nettyClientHandlerInner.sendMSG("writeWumingStatus@@" + new Random().nextInt(20000));Thread.sleep(2000);nettyClientHandlerInner.sendMSG("writePazhanfoStatus@@" + new Random().nextInt(20000));nettyClientHandlerInner.sendMSG("pkRecord@@" + new Random().nextInt(20000));} catch (InterruptedException e) {e.printStackTrace();}}}}).start();init();connectToServer(nettyClientHandlerInner);}public static void init() {workerGroup = new NioEventLoopGroup();b = new Bootstrap(); // (1)b.group(workerGroup); // (2)b.channel(NioSocketChannel.class); // (3)b.option(ChannelOption.SO_KEEPALIVE, true); // (4)b.handler(new ChannelInitializer<SocketChannel>() {@Overridepublic void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast(new LineBasedFrameDecoder(1024));ch.pipeline().addLast(new StringDecoder());ch.pipeline().addLast(nettyClientHandlerInner);}});channelFutureListener=new ChannelFutureListener() {@Overridepublic void operationComplete(ChannelFuture channelFuture) throws Exception {if(!channelFuture.isSuccess()){channelFuture.channel().eventLoop().schedule(new Runnable() {@Overridepublic void run() {doReconnect();}},3,TimeUnit.SECONDS);}else{System.out.println("重连成功");}}};}public static void connectToServer(NettyClientHandlerInner nettyClientHandler) {try {// Start the client.f = b.connect("127.0.0.1", 10004).sync(); // (5)f.addListener(new ChannelFutureListener() {@Overridepublic void operationComplete(ChannelFuture channelFuture) throws Exception {if(!channelFuture.isSuccess()){System.out.println("重试");channelFuture.channel().eventLoop().schedule(new Runnable() {@Overridepublic void run() {doReconnect();}},3,TimeUnit.SECONDS);}else{}}});// Wait until the connection is closed.f.channel().closeFuture().sync();} catch (InterruptedException e) {e.printStackTrace();}}public static void doReconnect(){ChannelFuture future=b.connect("127.0.0.1", 10004);future.addListener(channelFutureListener);}
}
NettyClientHandlerInner
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;import java.io.IOException;
import java.util.concurrent.TimeUnit;@ChannelHandler.Sharable
class NettyClientHandlerInner extends ChannelInboundHandlerAdapter {ChannelHandlerContext ctxOut;//通道就绪事件(就是在bootstrap启动助手配置中addlast了handler之后就会触发此事件)//但我觉得也可能是当有客户端连接上后才为一次通道就绪public void channelActive(ChannelHandlerContext ctx) throws IOException, InterruptedException {System.out.println("客户端消息,通道激活,可以发送消息了");ctxOut=ctx;}//数据读取事件public void channelRead(ChannelHandlerContext ctx, Object msg) {//传来的消息包装成字节缓冲区String byteBuf = (String) msg;
// ByteBuf byteBuf = (ByteBuf) msg;//Netty提供了字节缓冲区的toString方法,并且可以设置参数为编码格式:CharsetUtil.UTF_8System.out.println("客户端读取服务返回的数据:" + byteBuf);}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // (4)// Close the connection when an exception is raised.cause.printStackTrace();System.out.println(cause.getMessage());ctx.close();}public void sendMSG(String msg){ctxOut.writeAndFlush(Unpooled.copiedBuffer(msg+"\r\n", CharsetUtil.UTF_8));}@Overridepublic void channelInactive(ChannelHandlerContext ctx) throws Exception {super.channelInactive(ctx);System.out.println("与服务器断开");ctx.channel().eventLoop().schedule(new Runnable() {@Overridepublic void run() {nettyClient.doReconnect();}}, 3, TimeUnit.SECONDS);ctx.close();}
}
总结
要实现重连,有三个地方需要注意
- 对连接成功的ChannelFuture进行监听,调用doReconnect
- 实现如上的doReconnect
- 在NettyClientHandlerInner中重写channelInactive,再次调用doReconnect
@Overridepublic void channelInactive(ChannelHandlerContext ctx) throws Exception {super.channelInactive(ctx);System.out.println("与服务器断开");ctx.channel().eventLoop().schedule(new Runnable() {@Overridepublic void run() {nettyClient.doReconnect();}}, 3, TimeUnit.SECONDS);ctx.close();}
相关文章:
java-netty客户端断线重启
背景 经常会遇到netty客户端,因为网络等多种原因而断线,需要自动重连 核心 就是对连接服务端成功后,对ChannelFuture进行监听,核心代码如下 f b.connect("127.0.0.1", 10004).sync(); // (5)f.addListener(new Chan…...
MySQL的基础用法一
数据库的操作 对库的操作 SQL通用语法规则介绍 创建数据库 使用数据库 查询所有数据库 查询当前数据库 删除数据库 对库中表的操作 创建一个表 查询当前数据库所有表 查询表结构 查询指定表的建表语句 🚘🚘🚘正片开始 SQL通用语…...
Linux:进程地址空间
目录 一、虚拟地址 二、进程地址空间 一、虚拟地址 父进程和子进程之间,代码共享,而数据可能会发生修改,所以当其中一个进程要写入数据时,则发生写时拷贝,各自私有一份。 现在有源文件内容如下所示。 int glob_val …...
数据结构:树、森林
二叉树与树结构差异 树(一般树):树是一种数据结构,其中每个节点可以有任意数量的子节点(除了根节点和叶子节点外)。因此,一般树的节点在数组中的表示并不是那么直接,特别是当树不是完…...
AI Agent应用出路到底在哪?
1 Agent/Function Call 的定义 Overview of a LLM-powered autonomous agent system: Agent学会调用外部应用程序接口,以获取模型权重中缺失的额外信息(预训练后通常难以更改),包括当前信息、代码执行能力、专有信息源…...
一文了解构建工具——Maven与Gradle的区别
目录 一、Maven和Gradle是什么? 构建工具介绍 Maven介绍 Gradle介绍 二、使用时的区别: 1、新建项目 Maven: Gradle: 2、配置项目 Maven: Gradle: 3、构建项目——生成项目的jar包 Gradle&…...
electron介绍
Electron中文文档 Electron是什么? Electron是一个使用 JavaScript、HTML 和 CSS 构建桌面应用程序的框架。 Electron 允许开发者使用前端技术栈来创建可以在 Windows、macOS 和 Linux 等多个操作系统上运行的桌面应用程序。 Electron 本质上是一个运行在桌面操作…...
Redis-持久化
首先,我们明白一个概念, 硬盘>持久 内存>不持久 而Redis是一个内存数据库,不持久,相比于Mysql这样的关系型数据库,最明显的特点是快/效率高 为了保证速度快,数据要保存再内存中,为了持久,存储在硬盘上 所以redis决定: 插入>内存+硬盘(硬盘是为了在re…...
封装轮播图 (因为基于微博小程序,语法可能有些出入,如需使用需改标签)
这是在组件中使用,基于微博语法 <template><wbx-view class"" style"width: 100vw;height: 70vh;"><WBXswiper change"gaibian" :vertical"false" :current"current" indicatorActiveColor"…...
【Ubuntu】minicom安装、配置、使用以及退出
目录 1 安装 2 配置 3 使用 4 退出 minicom是一个串口通信的工具,以root权限登录系统,可用来与串口设备通信。 1 安装 sudo apt-get install minicom 2 配置 使用如下命令进入配置界面: sudo minicon -s 进入配置界面后,…...
MYSQL的监控
1. MySQL服务器都提供了哪几种类型的日志文件?说明每种日志的用途。 Error log:启动、关闭和异常有关的诊断信息 General query log:服务器从客户端收到的所有语句 Slow query log:需要很长时间执行的查询 Audit log:企业版基于策略的审计 Binary…...
CTF ciscn_2019_web_northern_china_day1_web2
ciscn_2019_web_northern_china_day1_web2 BEGIN 拿到题目,先看看 这里发现一个很像提示的东西,然后发现下面是一堆小电视商品,有lv等级和金钱,所以这题的入口可能就是再lv6和这个资金募集上 然后点击下next,看看页…...
linux中vim编辑器的应用实例
前言 Linux有大量的配置文件,其中编辑一些配置文件,最常用的工具就是 Vim ,本文介绍一个实际应用的Vim编辑器开发文档的实例。 Vim是一个类似于Vi的著名的功能强大、高度可定制的文本编辑器,在Vi的基础上改进和增加了很多特性。…...
智慧城市交通管理中的云端多车调度与控制
城市交通管理中的云端多车调度与控制 智慧城市是 21世纪的城市基本发展方向,为了实现智慧城市建设的目标,人们需要用现代化的手段去管理和控制城市中的各种资源和设施。智能交通控制与管理是智慧城市中不可缺少的一部分,因为现代城市交通系统…...
分治(归并排序)
一、基本思路 我们以一个归并排序为例。 . - 力扣(LeetCode) 归并排序的思想:得到两个有序数组,把两个有序数组合并,传到下一层递归,一直得到两个有序数组,一直合并,最后就能得到有…...
小学生为什么要学英语
小学生需要学习英语的原因有很多,以下是其中的一些原因(毕竟我也会累滴(* ̄▽ ̄*)): 1. 全球化交流:英语是国际交流的通用语言,学习英语可以帮助小学生更好地融入全球化的社会环境&am…...
企业云存储如何收费?企业云存储收费标准
企业云存储如何收费?企业云存储的收费方式因不同的服务提供商和具体的服务选项而异,通常从用户数量、存储容量、功能、混合收费、按需定价、定制化、功能模块等多个方面进行考量。以下是对其多方面收费方式的详细介绍: 1.按用户数量收费 适用…...
一步步教你LangGraph Studio:可视化调试基于LangGraph构建的AI智能体
之前我们在第一时间介绍过使用LangChain的LangGraph开发复杂的RAG或者Agent应用,随着版本的迭代,LangGraph已经成为可以独立于LangChain核心,用于开发多步骤、面向复杂任务、支持循环的AI智能体的强大框架。 近期LangGraph推出了一个使得复杂…...
用SpringBoot打造先进的学科竞赛管理系统
1绪 论 1.1研究背景 当今时代是飞速发展的信息时代。在各行各业中离不开信息处理,这正是计算机被广泛应用于信息管理系统的环境。计算机的最大好处在于利用它能够进行信息管理。使用计算机进行信息控制,不仅提高了工作效率,而且大大的提高了其…...
Linux入门攻坚——34、nsswitch、pam、rsyslog和loganalyzer前端展示工具
nsswitch:network service switch 名称解析:name <---> id 认证服务:用户名、密码验证或token验证等 名称解析和认证服务都涉及查找位置,即保存在哪里。如linux认证,passwd、shadow,是在文件中&…...
从Concur到特斯拉:为什么伟大产品始于“丑陋”的1.0版本
1. 从一笔74亿美元的收购案说起:为什么别急着给1.0产品判死刑 前几天翻看一些旧资料,看到一篇2014年的行业评论,讲的是德国软件巨头SAP以74亿美元的天价,收购了一家名叫Concur的西雅图公司。当时很多人觉得不可思议,Co…...
构建本地语音智能体:基于Go与OpenClaw的实时交互系统
1. 项目概述:一个能听懂你说话的本地智能体伙伴如果你和我一样,对传统的、需要打字输入、反应迟缓的AI助手感到厌倦,总幻想着能有一个像电影《Her》里Samantha那样的智能伙伴,能用最自然的语音与你交流,甚至能帮你执行…...
短视频矩阵系统技术选型:从自研到 SaaS 的成本与收益分析
前言在短视频运营规模化的今天,几乎所有有一定规模的团队都面临着一个关键的技术决策:是自研矩阵管理系统,还是选择成熟的 SaaS 解决方案。很多团队在初期都会选择自研,认为这样可以更好地满足个性化需求,但最终往往陷…...
Python自动化反向链接侦察工具:从爬虫原理到SEO实战应用
1. 项目概述:一个反向链接自动化侦察兵如果你做过网站运营、SEO或者内容营销,那你一定对“反向链接”这个词不陌生。简单来说,当网站A上有一个链接指向了你的网站B,这个链接就是你的一个反向链接。在搜索引擎的“世界观”里&#…...
从Excel到BI Launchpad:SAP BW/4HANA数据分析实战,手把手教你用BO做报表
从Excel到BI Launchpad:SAP BW/4HANA数据分析实战指南 1. 企业级数据分析的进化之路 在当今数据驱动的商业环境中,企业数据分析正经历着从静态报表到动态洞察的革命性转变。传统Excel虽然灵活易用,但在处理海量数据、实现实时协作和构建企业级…...
Ctool架构深度解析:模块化开发工具集的高效实现方案
Ctool架构深度解析:模块化开发工具集的高效实现方案 【免费下载链接】Ctool 程序开发常用工具 chrome / edge / firefox / utools / windows / linux / mac 项目地址: https://gitcode.com/gh_mirrors/ct/Ctool 在程序开发过程中,开发者经常需要在…...
Mac上如何用DistroAV插件实现无线多机位直播:NDI技术完整指南
Mac上如何用DistroAV插件实现无线多机位直播:NDI技术完整指南 【免费下载链接】obs-ndi DistroAV (formerly OBS-NDI): NDI integration for OBS Studio 项目地址: https://gitcode.com/gh_mirrors/ob/obs-ndi 还在为Mac上的OBS直播设置烦恼吗?想…...
Andorid下给PDF盖骑缝章的方法—安卓手机批量盖骑缝章的方法
Andorid下给PDF盖骑缝章的方法,安卓手机批量盖骑缝章的方法。一、准备印章图片1。不需要制作为透明的印章,用白底Png格式图片即可,白底图片盖章时软件会自动透明并融合。2。印章边线与图片四边不要有空隙,如下:错误的&…...
我们给大模型接上了CI/CD流水线,测试通过率从60%飙升到95%
在软件测试领域,质量保障体系的进化从未停歇。当大语言模型(LLM)从实验性项目走向生产环境,测试团队面临一个尖锐的矛盾:模型迭代速度以天甚至小时计,而传统的人工评估与回归测试却需要数周。我们团队在将大…...
Python金融数据分析实战:从数据清洗到LLM智能问答机器人构建
1. 项目概述:一个金融数据分析与智能问答的实战项目 最近在整理一些数据分析的实战项目,正好翻到了之前为Forage BCGX GenAI项目做的一个金融分析案例。这个项目麻雀虽小,五脏俱全,它完整地走了一遍从原始数据清洗、指标计算、可视…...
