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 实现心跳检测和断线重连相关推荐

  1. netty心跳过程中 发送消息失败_netty心跳机制和断线重连(四)

    心跳是为了保证客户端和服务端的通信可用.因为各种原因客户端和服务端不能及时响应和接收信息.比如网络断开,停电 或者是客户端/服务端 高负载. 所以每隔一段时间 客户端发送心跳包到客户端  服务端做出心 ...

  2. PowerShell实现“机器人定时在企业微信群中发送消息”功能(上)

    本章实现 由于篇幅较多,会拆分为上.下两部分来写. 本章实现: 01.如何在企业微信中添加群机器人 02.简单用机器人发送一条消息(postman实现) 03.powershell打开 04.简单用机 ...

  3. RabbitMQ消息队列,发送消息失败、消息持久化、消费者失败处理方法和发送消息

    项目是使用springboot项目开发的,前是代码实现,后面有分析发送消息失败.消息持久化.消费者失败处理方法和发送消息解决方法及手动确认的模式 先引入pom.xml <!--rabbitmq- ...

  4. MeterSphere实现“机器人定时在企业微信群中发送消息”功能

    背景 之前有过用PowerShell实现"机器人定时在企业微信群中发送消息"功能,并有输出相关教程. 但发现有一些问题:比如电脑关机了导致任务不能如期启动,于是在摸索中找到可替代P ...

  5. PowerShell实现“机器人定时在企业微信群中发送消息”功能(下)

    本章实现 由于篇幅较多,会拆分为上.下两部分来写. 本章实现: 06.机器人定时在企业微信群中发送消息功能 上章实现 01.如何在企业微信中添加群机器人 02.简单用机器人发送一条消息(postman ...

  6. macM1下PD虚拟机中ubuntu安装git过程中apt-get update失败、E: 部分索引文件下载失败等问题

    macM1下PD虚拟机中ubuntu安装git过程中apt-get update失败.E: 部分索引文件下载失败等问题 问题描述 怀疑1:更新所用的软件源的问题 怀疑2:多架构支持导致在更新源时链接不 ...

  7. java实现如何定时给微信群中发送消息

    大家好,我是雄雄. 前言 前几天,发了一个系列这样的文章,如下所示: java实现每日给女友微信发送早安等微信信息 java实现给微信群中定时推送消息 如何将每日新闻添加到自己博客中,发送到微信群中 ...

  8. 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是否已经安装的时候,这些在安装 ...

  9. 在idea中往Kafka发送消息失败

    今天在学习Kafka整合Springboot项目的时候,往Kafka发送消息,消费者一直消费不到,ip地址,端口号,防火墙的状态都没有发现问题.后来发现是因为idea没有连接到虚拟机的,一直在找本机的 ...

最新文章

  1. JQuery插件:ScrollTo平滑滚动到页面指定位置
  2. tableau可视化函数使用案例(六十七)-如何用Tableau获取数据并对数据进行操作?
  3. 25 类:接口 抽象父类 多态 鸭子类型 格式化方法与析构方法 反射 异常处理 自定义异常 断言...
  4. go 从入门到精通(二)基本数据类型和操作符
  5. 临沂大学3加4计算机专业,临沂大学2021年电子信息(计算机技术方向) 硕士研究生调剂工作细则...
  6. IE图标消失 HTML文件图标变为未知图标的解决方法
  7. STL之string类型
  8. Oracle修改表存储参数,Oracle存储结构之参数文件
  9. 简述php语言的特点是_PHP语言有哪些优势和特点(一)
  10. 发展大数据还有啥问题:数据孤岛、技术差距、人才短缺
  11. Windows下Python3.6安装PIL
  12. 大数据的核心价值表现在哪里
  13. 急速了解vue生命周期
  14. spring-boot-route(十九)spring-boot-admin监控服务
  15. redis php 使用实例
  16. FileUtils(文件读写操作工具类)
  17. 中国省,市,区 json数据
  18. Error occurred when evaluating apply
  19. 现在做什么能挣钱?想要在互联网赚钱,一定要懂这些!
  20. Git创建新分支并提交到github

热门文章

  1. 学会这10大高性能开发技术,轻松躲过裁员名单!
  2. 寻找榜样的力量!CSDN【百万人学 AI】评选活动重磅启动
  3. 2019年6月 阿里技术面试题集锦(28道含答案)
  4. 行啊,人工智能玩大了!
  5. 华为智能计算发布FusionServer Pro智能服务器
  6. linux iio 设备驱动,Linux设备驱动之IIO子系统——IIO框架数据读取-Go语言中文社区...
  7. python异常处理try判断整数_Python 异常处理 try、except、raise
  8. Vim快速移动光标至行首和行尾
  9. PLSQL 日期格式修改
  10. IntelliJ IDEA 2020.1 快速查找文件