基于Netty5.0案例八服务端心跳包

来源:互联网 发布:软件造价评估公司 编辑:程序博客网 时间:2024/06/07 01:54

前言介绍:
本案例主要介绍服务端心跳包使用
本案例心跳包主要用于服务端在读、写、读写超时内做出的相应处理。
代码拿到手后可以最好测试下,事必躬亲,无论案例如何明白也得自己测试。

环境需求:【一下内容下文提供下载】
1、Java
1.1、jdk1.7
1.2、Eclipse
2、netty-all-5.0.0.Alpha1.jar

代码部分:

ChildChannelHandler.java

import java.nio.charset.Charset;import java.util.concurrent.TimeUnit;import io.netty.buffer.ByteBuf;import io.netty.buffer.Unpooled;import io.netty.channel.ChannelInitializer;import io.netty.channel.socket.SocketChannel;import io.netty.handler.codec.DelimiterBasedFrameDecoder;import io.netty.handler.codec.Delimiters;import io.netty.handler.codec.FixedLengthFrameDecoder;import io.netty.handler.codec.LineBasedFrameDecoder;import io.netty.handler.codec.string.StringDecoder;import io.netty.handler.codec.string.StringEncoder;import io.netty.handler.timeout.IdleStateHandler;import io.netty.util.CharsetUtil;public class ChildChannelHandler extends ChannelInitializer{@Overrideprotected void initChannel(SocketChannel e) throws Exception {System.out.println("报告");System.out.println("信息:有一客户端链接到本服务端");System.out.println("IP:" + e.localAddress().getHostName());System.out.println("Port:" + e.localAddress().getPort());System.out.println("报告完毕");/*** 心跳包* 1、readerIdleTimeSeconds 读超时时间* 2、writerIdleTimeSeconds 写超时时间* 3、allIdleTimeSeconds 读写超时时间* 4、TimeUnit.SECONDS 秒[默认为秒,可以指定]*/e.pipeline().addLast(new IdleStateHandler(2, 2, 2));// 基于换行符号解码器e.pipeline().addLast(new LineBasedFrameDecoder(1024));// 解码转Stringe.pipeline().addLast(new StringDecoder(Charset.forName("GBK")));// 编码器 Stringe.pipeline().addLast(new StringEncoder(Charset.forName("GBK")));// 处理心跳 【放在编码解码的下面,因为这个是通道有处理顺序】e.pipeline().addLast(new MyIdleHandler());// 在管道中添加我们自己的接收数据实现方法e.pipeline().addLast(new MyServerHanlder());}}

MyIdleHandler.java

import io.netty.channel.ChannelHandlerAdapter;import io.netty.channel.ChannelHandlerContext;import io.netty.handler.timeout.IdleState;import io.netty.handler.timeout.IdleStateEvent;public class MyIdleHandler extends ChannelHandlerAdapter {@Overridepublic void userEventTriggered(ChannelHandlerContext ctx, Object evt)throws Exception {if (evt instanceof IdleStateEvent) {IdleStateEvent e = (IdleStateEvent) evt;if (e.state() == IdleState.READER_IDLE) {System.out.println("--- Reader Idle ---");ctx.writeAndFlush("读取等待:客户端你在吗... ...\r\n");// ctx.close();} else if (e.state() == IdleState.WRITER_IDLE) {System.out.println("--- Write Idle ---");ctx.writeAndFlush("写入等待:客户端你在吗... ...\r\n");// ctx.close();} else if (e.state() == IdleState.ALL_IDLE) {System.out.println("--- All_IDLE ---");ctx.writeAndFlush("全部时间:客户端你在吗... ...\r\n");}}}}

MyServerHanlder.java

import java.util.Date;import io.netty.buffer.ByteBuf;import io.netty.buffer.Unpooled;import io.netty.channel.ChannelHandlerAdapter;import io.netty.channel.ChannelHandlerContext;import io.netty.handler.codec.bytes.ByteArrayDecoder;public class MyServerHanlder extends ChannelHandlerAdapter{/** channelAction** channel 通道* action 活跃的** 当客户端主动链接服务端的链接后,这个通道就是活跃的了。也就是客户端与服务端建立了通信通道并且可以传输数据**/public void channelActive(ChannelHandlerContext ctx) throws Exception {System.out.println(ctx.channel().localAddress().toString()+" channelActive");//通知您已经链接上客户端String str = "您已经开启与服务端链接"+" "+ctx.channel().id()+new Date()+" "+ctx.channel().localAddress();ctx.writeAndFlush(str);}/** channelInactive** channel 通道* Inactive 不活跃的** 当客户端主动断开服务端的链接后,这个通道就是不活跃的。也就是说客户端与服务端的关闭了通信通道并且不可以传输数据**/public void channelInactive(ChannelHandlerContext ctx) throws Exception {System.out.println(ctx.channel().localAddress().toString()+" channelInactive");}/** channelRead** channel 通道* Read 读** 简而言之就是从通道中读取数据,也就是服务端接收客户端发来的数据* 但是这个数据在不进行解码时它是ByteBuf类型的后面例子我们在介绍**/public void channelRead(ChannelHandlerContext ctx, Object msg)throws Exception {//注意此处已经不需要手工解码了System.out.println(ctx.channel().id()+""+new Date()+" "+msg);//通知您已经链接上客户端[给客户端穿回去的数据加个换行]String str = "服务端收到:"+ctx.channel().id()+new Date()+" "+msg+"\r\n";//发送给客户端【可以开启关闭用于测试心跳包】ctx.writeAndFlush(str);}/** channelReadComplete** channel 通道* Read 读取* Complete 完成** 在通道读取完成后会在这个方法里通知,对应可以做刷新操作* ctx.flush()**/public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {ctx.flush();}/** exceptionCaught** exception 异常* Caught 抓住** 抓住异常,当发生异常的时候,可以做一些相应的处理,比如打印日志、关闭链接**/public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)throws Exception {ctx.close();System.out.println("异常信息:\r\n"+cause.getMessage());}}

NettyServer.java

package com.itstack.netty.idle;import io.netty.bootstrap.ServerBootstrap;import io.netty.channel.ChannelFuture;import io.netty.channel.ChannelOption;import io.netty.channel.EventLoopGroup;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.nio.NioServerSocketChannel;public class NettyServer {public static void main(String[] args) {try {System.out.println("服务端开启等待连接... ...");new NettyServer().bing(7397);} catch (Exception e) {e.printStackTrace();}}public void bing(int port) throws Exception{EventLoopGroup bossGroup = new NioEventLoopGroup();EventLoopGroup workGroup = new NioEventLoopGroup();try {ServerBootstrap b = new ServerBootstrap();b.group(bossGroup, workGroup);b.channel(NioServerSocketChannel.class);b.option(ChannelOption.SO_BACKLOG, 1024);b.childHandler(new ChildChannelHandler());ChannelFuture f = b.bind(port).sync();f.channel().closeFuture().sync();} finally {bossGroup.shutdownGracefully();workGroup.shutdownGracefully();}}}


0 0
原创粉丝点击