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,是在文件中&…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...
【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
在WSL2的Ubuntu镜像中安装Docker
Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包: for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...
vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...
Git常用命令完全指南:从入门到精通
Git常用命令完全指南:从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...
Linux中《基础IO》详细介绍
目录 理解"文件"狭义理解广义理解文件操作的归类认知系统角度文件类别 回顾C文件接口打开文件写文件读文件稍作修改,实现简单cat命令 输出信息到显示器,你有哪些方法stdin & stdout & stderr打开文件的方式 系统⽂件I/O⼀种传递标志位…...
【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...
JS红宝书笔记 - 3.3 变量
要定义变量,可以使用var操作符,后跟变量名 ES实现变量初始化,因此可以同时定义变量并设置它的值 使用var操作符定义的变量会成为包含它的函数的局部变量。 在函数内定义变量时省略var操作符,可以创建一个全局变量 如果需要定义…...
