- 浏览: 223880 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
啊嘞嘞勒:
游戏结束无法显示
自己制作的 java 版 2048游戏 -
VIP庚:
dufangyu1990 写道VIP庚 写 ...
Android 视频通话(一) -
dufangyu1990:
VIP庚 写道dufangyu1990 写 ...
Android 视频通话(一) -
VIP庚:
dufangyu1990 写道VIP庚 写道dufangyu1 ...
Android 视频通话(一) -
dufangyu1990:
VIP庚 写道dufangyu1990 写道VIP庚 写道du ...
Android 视频通话(一)
一 实现心跳检测
原理:当服务端每隔一段时间就会向客户端发送心跳包,客户端收到心跳包后同样也会回一个心跳包给服务端
一般情况下,客户端与服务端在指定时间内没有任何读写请求,就会认为连接是idle(空闲的)的。此时,客户端需要向服务端发送心跳消息,来维持服务端与客户端的链接。那么怎么判断客户端在指定时间里没有任何读写请求呢?netty中为我们提供一个特别好用的IdleStateHandler来干这个苦差事!
在服务端工作线程中添加:
这个处理器,它的作用就是用来检测客户端的读取超时的,该类的第一个参数是指定读操作空闲秒数,第二个参数是指定写操作的空闲秒数,第三个参数是指定读写空闲秒数,当有操作操作超出指定空闲秒数时,便会触发UserEventTriggered事件。所以我们只需要在自己的handler中截获该事件,然后发起相应的操作即可(比如说发起心跳操作)。以下是我们自定义的handler中的代码:
也就是说 服务端在10s内未进行读写操作,就会向客户端发送心跳包,客户端收到心跳包后立即回复心跳包给服务端,此时服务端就进行了读操作,也就不会触发IdleState.READER_IDLE(未读操作状态),若客户端异常掉线了,并不能响应服务端发来的心跳包,在25s后就会触发IdleState.READER_IDLE(未读操作状态),此时服务器就会将通道关闭
客户端代码略
二 客户端实现断线重连
原理当客户端连接服务器时
会返回一个ChannelFuture的对象,我们对这个对象进行监听
代码如下:
监听到连接服务器失败时,会在3秒后重新连接(执行doConnect方法)
这还不够,当客户端掉线时要进行重新连接
在我们自己定义逻辑处理的Handler中
channel是客户端与服务器之间通信的通道,和socket类似,当客户端与服务器连接成功后,会将chanel保存。这里是客户端与服务器断开连接后进行重连,所以要将原先的通道变成空
原理:当服务端每隔一段时间就会向客户端发送心跳包,客户端收到心跳包后同样也会回一个心跳包给服务端
一般情况下,客户端与服务端在指定时间内没有任何读写请求,就会认为连接是idle(空闲的)的。此时,客户端需要向服务端发送心跳消息,来维持服务端与客户端的链接。那么怎么判断客户端在指定时间里没有任何读写请求呢?netty中为我们提供一个特别好用的IdleStateHandler来干这个苦差事!
在服务端工作线程中添加:
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<SocketChannel>() { @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 楼
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应用理解的更深入了一点
发表评论
-
2018 Flag
2019-02-23 16:24 456一年多没写博客了,2018年工作太忙了,但是也收获到 ... -
PopupWindow 模拟通知弹出
2017-10-09 10:11 1271最近遇到一个需求,下面记录下实现方法 以及遇到的一些坑 需求 ... -
在Android源码下编译jni所需要知道的事~
2017-03-21 16:40 2989以下只是自己的一些总结,欢迎讨论 通过NDK编译jni网上有 ... -
Android 通过PathMeasure和Path实现动画
2016-12-24 17:07 5899最近一直在学习android框架,也就没怎么写博客了。前几 ... -
解决 Android 写入图片后 系统图库中看不到
2016-10-30 17:47 3231将一个图片通过写入外部存储后,打开系统图库找不到该图片 ... -
Android 6.0 对权限的处理
2016-09-01 14:15 3068最近要将拍的照片写入到手机外部存储中,开始测试时一点问题都 ... -
Android Dialog设置TYPE_SYSTEM_ALERT 有些手机不能显示问题
2016-08-08 11:46 11696在对话框初始的时候,设置 mProgressDialo ... -
Java 关于在公网上无法发送UDP数据给客户端问题
2016-05-19 00:22 5678最近在弄语音通话,当在局域网测试程序的时候,tcp和udp ... -
SnackBar 中添加多个按钮
2016-05-11 13:26 3998最近无意间看到一篇文章,解决了我很久以前的困扰 简单介 ... -
根据汉字拼音排序
2016-05-05 19:38 2361最近在做操作联系人数据这一块,当读取系统表中的联系人的数据 ... -
Android 开源图表库 ------ MPAndroidChart
2016-04-16 18:27 0最近在开发心率方面,要绘制心率图,准备自己写自定义view ... -
Android 命名空间和自定义属性
2016-03-18 13:06 4289在布局文件中经常看到 xmlns:android=&q ... -
Android 自定义属性和命名空间
2016-03-18 13:03 0在布局文件中经常看到 xmlns:android=&q ... -
组件之间通信------ EventBus 学习心得
2016-03-07 22:12 4715Android 线程、组件之间通信可以通过Handler消息处 ... -
常见的几种排序方法
2016-03-07 18:47 775由于最近要应付面试,所以把几个常见的排序方法有复习了一下。 ... -
关于Fragment所需要知道的概念
2016-03-02 00:16 1541可以把Fragment想成Activity中的模块,这个模 ... -
Android沉浸式通知栏的一个开源库SystemBarTint简单使用
2016-02-20 20:54 4392什么是沉浸式设模式?沉浸模式计就是把用来导航的各种界面操作 ... -
Netty4.0 实现心跳检测和客户端断线重连
2016-02-17 21:41 1一 实现心跳检测 原理:当服务端每隔一段时间就会向客户端发送心 ... -
Netty4.0 实现心跳检测和客户端断线重连
2016-02-17 21:41 1一 实现心跳检测 原理:当服务端每隔一段时间就会向客户端发送心 ... -
Struts学习的总结
2016-02-06 21:07 1900一 Struts使用步骤 1 导入Struts jar包 2 ...
相关推荐
在本文中,我们将深入探讨如何利用 Netty 和 WebSocket 实现心跳检测和断线重连机制。 首先,我们需要理解 WebSocket 协议。WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议,它为客户端和服务器提供了低...
springboot整合 netty做心跳检测 springboot整合 netty做心跳检测 springboot整合 netty做心跳检测 springboot整合 netty做心跳检测 springboot整合 netty做心跳检测 springboot整合 netty做心跳检测 springboot整合...
配置maven添加io.netty 在com.zhao的包下的文件,可以自行修改使用
Netty 4.0 提供了强大的网络编程能力,使得实现文件分片上传、断点续传和权限校验变得相对简单。通过自定义处理器和策略,我们可以构建高效且安全的文件上传系统。rrkd-file-client和rrkd-file-server这两个文件可能...
netty使用自带工具类实现断线重连和心跳包
Springboot2.0.8集成 netty4 ,使用protobuf作为ping的数据交换,比json更加的小巧,占用数据量更小... - 断线重连 - 计算ping值(支持到微秒) - 其他子业务模块(架子已搭进去) - 为了方便测试,项目已经支持跨域访问
Netty4.0全部jar包.开发时候只需要倒入总的哪一个netty4.0.jar就行了 后缀为resources.jar的全部是源码。 简单的代码例子在netty-example-resources.jar里面。
在本篇Netty4.0学习笔记中,我们将聚焦于如何在实际应用中混合使用`coder`和`handler`,这是Netty框架中非常关键的一部分,对于构建高性能、低延迟的网络应用程序至关重要。Netty是一个用Java编写的异步事件驱动的...
以下是实现心跳和重连的基本步骤: 1. **创建心跳消息**: 定义一个心跳消息类型,通常是简单的结构,如自定义的 ByteBuf 或 ProtocolBuffer。 2. **设置心跳发送器**: 创建一个 ChannelInboundHandler,负责在预设...
8. **线程模型**:Netty 采用 NIO(非阻塞 I/O)模型,结合 Epoll(在 Linux 下)和 Kqueue(在 BSD 系统下)系统调用,实现了高效率的并发处理。 9. **ChannelFuture**:用于异步操作的结果,可以注册监听器来处理...
Netty 是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。在这个“Netty4.0 http案例”中,我们将深入探讨如何利用Netty 4.0 实现HTTP服务,以及客户端如何通过HTTP...
NIO socket开发,netty4.0工具包。
Netty 4.0.45提供了高度优化的NIO(非阻塞I/O)和EPOLL(用于Linux系统的高效I/O)实现,确保了在处理大量并发连接时的性能。 在Socket开发中,Netty的ChannelHandlerContext和EventLoopGroup等概念非常关键。...
netty案例,netty4.1中级拓展篇八《Netty心跳服务与断线重连》源码 https://mp.weixin.qq.com/s?__biz=MzIxMDAwMDAxMw==&mid=2650724845&idx=1&sn=8631c590ff4876ba0b7af64df16fc54b&scene=19#wechat_redirect
在“基于netty_4.0.26的心跳检测”这个主题中,我们将深入探讨如何在Netty 4.0.26版本中实现心跳检测机制,以确保网络连接的稳定性和可靠性。 心跳检测是网络通信中的一个重要概念,主要用于检测客户端与服务器之间...
在 Netty 4.0 中,引入了一系列重大改进和变化,旨在提高性能、可维护性和易用性。以下是这些变化的详细说明: 1. **工程结构的改变**: - 包名从 org.jboss.netty 更改为 io.netty,反映了项目的独立性。 - ...
安卓基于netty4.x心跳,断线重连,状态监听,数据发送
基于springboot+netty实现的心跳检测源码+项目说明文档.zip (1),NioEventLoopGroup是一个处理I / O操作的多线程事件循环。 Netty为不同类型的传输提供各种EventLoopGroup实现。我们在此示例中实现了服务器端应用程序...
Netty 是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。这个压缩包包含的是Netty 4.0.0.CR3版本的相关资源,包括源码、示例以及API文档,对于学习和理解Netty的工作...
Netty4.0.54英文版API文档,与官网中文档内容一致,方便用户在离线环境下,开发Netty