netty心跳过程中 发送消息失败_Netty 4.0 实现心跳检测和断线重连
arg0.pipeline().addLast("ping", new IdleStateHandler(25, 15, 10,TimeUnit.SECONDS));
这个处理器,它的作用就是用来检测客户端的读取超时的,该类的第一个参数是指定读操作空闲秒数,第二个参数是指定写操作的空闲秒数,第三个参数是指定读写空闲秒数,当有操作操作超出指定空闲秒数时,便会触发UserEventTriggered事件。所以我们只需要在自己的handler中截获该事件,然后发起相应的操作即可(比如说发起心跳操作)。以下是我们自定义的handler中的代码:
/**
* 一段时间未进行读写操作 回调
*/
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt)
throws Exception {
// TODO Auto-generated method stub
super.userEventTriggered(ctx, evt);
if (evt instanceof IdleStateEvent) {
IdleStateEvent event = (IdleStateEvent) evt;
if (event.state().equals(IdleState.READER_IDLE)) {
//未进行读操作
System.out.println("READER_IDLE");
// 超时关闭channel
ctx.close();
} else if (event.state().equals(IdleState.WRITER_IDLE)) {
} else if (event.state().equals(IdleState.ALL_IDLE)) {
//未进行读写
System.out.println("ALL_IDLE");
// 发送心跳消息
MsgHandleService.getInstance().sendMsgUtil.sendHeartMessage(ctx);
}
}
}
也就是说 服务端在10s内未进行读写操作,就会向客户端发送心跳包,客户端收到心跳包后立即回复心跳包给服务端,此时服务端就进行了读操作,也就不会触发IdleState.READER_IDLE(未读操作状态),若客户端异常掉线了,并不能响应服务端发来的心跳包,在25s后就会触发IdleState.READER_IDLE(未读操作状态),此时服务器就会将通道关闭
客户端代码略
二 客户端实现断线重连
原理当客户端连接服务器时
bootstrap.connect(new InetSocketAddress(
serverIP, port));
会返回一个ChannelFuture的对象,我们对这个对象进行监听
代码如下:
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.util.Log;
import com.ld.qmwj.Config;
import com.ld.qmwj.MyApplication;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
/**
* Created by zsg on 2015/11/21.
*/
public class MyClient implements Config {
private static Bootstrap bootstrap;
private static ChannelFutureListener channelFutureListener = null;
public MyClient() {
}
// 初始化客户端
public static void initClient() {
NioEventLoopGroup group = new NioEventLoopGroup();
// Client服务启动器 3.x的ClientBootstrap
// 改为Bootstrap,且构造函数变化很大,这里用无参构造。
bootstrap = new Bootstrap();
// 指定EventLoopGroup
bootstrap.group(group);
// 指定channel类型
bootstrap.channel(NioSocketChannel.class);
// 指定Handler
bootstrap.handler(new ChannelInitializer() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
// 创建分隔符缓冲对象
ByteBuf delimiter = Unpooled.copiedBuffer("#"
.getBytes());
// 当达到最大长度仍没找到分隔符 就抛出异常
ch.pipeline().addLast(
new DelimiterBasedFrameDecoder(10000, true, false, delimiter));
// 将消息转化成字符串对象 下面的到的消息就不用转化了
//解码
ch.pipeline().addLast(new StringEncoder(Charset.forName("UTF-8")));
ch.pipeline().addLast(new StringDecoder(Charset.forName("GBK")));
ch.pipeline().addLast(new MyClientHandler());
}
});
//设置TCP协议的属性
bootstrap.option(ChannelOption.SO_KEEPALIVE, true);
bootstrap.option(ChannelOption.TCP_NODELAY, true);
bootstrap.option(ChannelOption.SO_TIMEOUT, 5000);
channelFutureListener = new ChannelFutureListener() {
public void operationComplete(ChannelFuture f) throws Exception {
// Log.d(Config.TAG, "isDone:" + f.isDone() + " isSuccess:" + f.isSuccess() +
// " cause" + f.cause() + " isCancelled" + f.isCancelled());
if (f.isSuccess()) {
Log.d(Config.TAG, "重新连接服务器成功");
} else {
Log.d(Config.TAG, "重新连接服务器失败");
// 3秒后重新连接
f.channel().eventLoop().schedule(new Runnable() {
@Override
public void run() {
doConnect();
}
}, 3, TimeUnit.SECONDS);
}
}
};
}
// 连接到服务端
public static void doConnect() {
Log.d(TAG, "doConnect");
ChannelFuture future = null;
try {
future = bootstrap.connect(new InetSocketAddress(
serverIP, port));
future.addListener(channelFutureListener);
} catch (Exception e) {
e.printStackTrace();
//future.addListener(channelFutureListener);
Log.d(TAG, "关闭连接");
}
}
}
监听到连接服务器失败时,会在3秒后重新连接(执行doConnect方法)
这还不够,当客户端掉线时要进行重新连接
在我们自己定义逻辑处理的Handler中
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
Log.d(Config.TAG, "与服务器断开连接服务器");
super.channelInactive(ctx);
MsgHandle.getInstance().channel = null;
//重新连接服务器
ctx.channel().eventLoop().schedule(new Runnable() {
@Override
public void run() {
MyClient.doConnect();
}
}, 2, TimeUnit.SECONDS);
ctx.close();
}
3
顶
1
踩
分享到:
2016-02-17 21:42
浏览 30989
评论
3 楼
VIP庚
2016-12-23
sdtzyb 写道
MsgHandle 这个里面写的是什么为什么需要把 MsgHandle.getInstance().channel = null;
弄成空。
能不能把提懂点详细代码
channel是客户端与服务器之间通信的通道,和socket类似,当客户端与服务器连接成功后,会将chanel保存。这里是客户端与服务器断开连接后进行重连,所以要将原先的通道变成空
2 楼
sdtzyb
2016-12-21
MsgHandle 这个里面写的是什么为什么需要把 MsgHandle.getInstance().channel = null;
弄成空。
能不能把提懂点详细代码
1 楼
newboy2004
2016-04-21
对netty应用理解的更深入了一点
netty心跳过程中 发送消息失败_Netty 4.0 实现心跳检测和断线重连相关推荐
- netty心跳过程中 发送消息失败_netty心跳机制和断线重连(四)
心跳是为了保证客户端和服务端的通信可用.因为各种原因客户端和服务端不能及时响应和接收信息.比如网络断开,停电 或者是客户端/服务端 高负载. 所以每隔一段时间 客户端发送心跳包到客户端 服务端做出心 ...
- PowerShell实现“机器人定时在企业微信群中发送消息”功能(上)
本章实现 由于篇幅较多,会拆分为上.下两部分来写. 本章实现: 01.如何在企业微信中添加群机器人 02.简单用机器人发送一条消息(postman实现) 03.powershell打开 04.简单用机 ...
- RabbitMQ消息队列,发送消息失败、消息持久化、消费者失败处理方法和发送消息
项目是使用springboot项目开发的,前是代码实现,后面有分析发送消息失败.消息持久化.消费者失败处理方法和发送消息解决方法及手动确认的模式 先引入pom.xml <!--rabbitmq- ...
- MeterSphere实现“机器人定时在企业微信群中发送消息”功能
背景 之前有过用PowerShell实现"机器人定时在企业微信群中发送消息"功能,并有输出相关教程. 但发现有一些问题:比如电脑关机了导致任务不能如期启动,于是在摸索中找到可替代P ...
- PowerShell实现“机器人定时在企业微信群中发送消息”功能(下)
本章实现 由于篇幅较多,会拆分为上.下两部分来写. 本章实现: 06.机器人定时在企业微信群中发送消息功能 上章实现 01.如何在企业微信中添加群机器人 02.简单用机器人发送一条消息(postman ...
- macM1下PD虚拟机中ubuntu安装git过程中apt-get update失败、E: 部分索引文件下载失败等问题
macM1下PD虚拟机中ubuntu安装git过程中apt-get update失败.E: 部分索引文件下载失败等问题 问题描述 怀疑1:更新所用的软件源的问题 怀疑2:多架构支持导致在更新源时链接不 ...
- java实现如何定时给微信群中发送消息
大家好,我是雄雄. 前言 前几天,发了一个系列这样的文章,如下所示: java实现每日给女友微信发送早安等微信信息 java实现给微信群中定时推送消息 如何将每日新闻添加到自己博客中,发送到微信群中 ...
- python包编译过程中出现: /usr/local/cuda-9.0/nvcc: No such file or directory问题的简单解决办法
在安装torch.sparse包的过程中,出现/usr/local/cuda-9.0/nvcc: No such file or directory的错误,而检查nvcc是否已经安装的时候,这些在安装 ...
- 在idea中往Kafka发送消息失败
今天在学习Kafka整合Springboot项目的时候,往Kafka发送消息,消费者一直消费不到,ip地址,端口号,防火墙的状态都没有发现问题.后来发现是因为idea没有连接到虚拟机的,一直在找本机的 ...
最新文章
- JQuery插件:ScrollTo平滑滚动到页面指定位置
- tableau可视化函数使用案例(六十七)-如何用Tableau获取数据并对数据进行操作?
- 25 类:接口 抽象父类 多态 鸭子类型 格式化方法与析构方法 反射 异常处理 自定义异常 断言...
- go 从入门到精通(二)基本数据类型和操作符
- 临沂大学3加4计算机专业,临沂大学2021年电子信息(计算机技术方向) 硕士研究生调剂工作细则...
- IE图标消失 HTML文件图标变为未知图标的解决方法
- STL之string类型
- Oracle修改表存储参数,Oracle存储结构之参数文件
- 简述php语言的特点是_PHP语言有哪些优势和特点(一)
- 发展大数据还有啥问题:数据孤岛、技术差距、人才短缺
- Windows下Python3.6安装PIL
- 大数据的核心价值表现在哪里
- 急速了解vue生命周期
- spring-boot-route(十九)spring-boot-admin监控服务
- redis php 使用实例
- FileUtils(文件读写操作工具类)
- 中国省,市,区 json数据
- Error occurred when evaluating apply
- 现在做什么能挣钱?想要在互联网赚钱,一定要懂这些!
- Git创建新分支并提交到github
热门文章
- 学会这10大高性能开发技术,轻松躲过裁员名单!
- 寻找榜样的力量!CSDN【百万人学 AI】评选活动重磅启动
- 2019年6月 阿里技术面试题集锦(28道含答案)
- 行啊,人工智能玩大了!
- 华为智能计算发布FusionServer Pro智能服务器
- linux iio 设备驱动,Linux设备驱动之IIO子系统——IIO框架数据读取-Go语言中文社区...
- python异常处理try判断整数_Python 异常处理 try、except、raise
- Vim快速移动光标至行首和行尾
- PLSQL 日期格式修改
- IntelliJ IDEA 2020.1 快速查找文件