netty 5 心跳
package com.server;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.timeout.IdleStateHandler;
public class server {
public static void main(String[] args){
// 创建一个 server 服务
ServerBootstrap server = new ServerBootstrap();
EventLoopGroup boss = new NioEventLoopGroup();
EventLoopGroup worker = new NioEventLoopGroup();
// 绑定
try{
server.group(boss, worker);
server.channel( NioServerSocketChannel.class);
server.childHandler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) throws Exception {
ch.pipeline().addLast(new IdleStateHandler(5, 5, 10));
ch.pipeline().addLast(new StringDecoder());
ch.pipeline().addLast(new StringEncoder());
ch.pipeline().addLast(new ServerHandler());
}
});
//netty3中对应设置如下
//bootstrap.setOption("backlog", 1024);
//bootstrap.setOption("tcpNoDelay", true);
//bootstrap.setOption("keepAlive", true);
//设置参数,TCP参数
server.option(ChannelOption.SO_BACKLOG, 2048);//serverSocketchannel的设置,链接缓冲池的大小
server.childOption(ChannelOption.SO_KEEPALIVE, true);//socketchannel的设置,维持链接的活跃,清除死链接
server.childOption(ChannelOption.TCP_NODELAY, true);//socketchannel的设置,关闭延迟发送
ChannelFuture future = server.bind(10001);
System.out.println("start!");
//等待服务端关闭
future.channel().closeFuture().sync();
}catch(Exception e){
e.printStackTrace();
}finally{
worker.shutdownGracefully();
boss.shutdownGracefully();
}
}
}
ServerHandler 代码
package com.server;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
public class ServerHandler extends SimpleChannelInboundHandler<String> {
@Override
public void userEventTriggered(final ChannelHandlerContext ctx, Object evt)
throws Exception {
if(evt instanceof IdleStateEvent){
IdleStateEvent event = (IdleStateEvent)evt;
if(event.state() == IdleState.ALL_IDLE){
System.out.println("你很久没有联系了");
ChannelFuture future = ctx.writeAndFlush("you will close");
future.addListener( new ChannelFutureListener(){
@Override
public void operationComplete(ChannelFuture future)
throws Exception {
// TODO Auto-generated method stub
ctx.channel().close();
}
});
}
}else{
super.userEventTriggered(ctx, evt);
}
}
@Override
protected void messageReceived(ChannelHandlerContext ctx, String msg)
throws Exception {
System.out.println(msg);
ctx.channel().writeAndFlush("hi");
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
throws Exception {
// TODO Auto-generated method stub
super.exceptionCaught(ctx, cause);
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
System.out.println("欢迎链接");
super.channelActive(ctx);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
System.out.println("断开链接");
super.channelInactive(ctx);
}
}
注意需要引入 netty 5 的jar包
ch.pipeline().addLast(new IdleStateHandler(5, 5, 10)); 给管道加入一个心跳事件, 5 读超时 5写超时 10 读写超时 超过5秒没有读就会发起一个读超时事件
Handler 中的 userEventTriggered 这个方法为心跳触发事件,当事件类型为 IdleStateEvent 为超时类型事件 当返回的状态为 IdleState.ALL_IDLE 为读写超时
秦水坡-杜撰