长连接有些情况下不会实时感知的如手机开了飞行模式,电脑关闭了WIFI等等此时服务器不能感知到长连接已经断开了此时一般会进行心跳检查的方式来判断长连接是否断开从而保证资源不会浪费。
客户端:
public class ChatClient {
public static void main(String[] args) {
//事件循环组
EventLoopGroup eventExecutors = new NioEventLoopGroup();
try {
//客户端的启动
Bootstrap bootstrap = new Bootstrap();
//处理事件,反射创建channel实例,处理的handler
bootstrap.group(eventExecutors).channel(NioSocketChannel.class).
handler(new ChatInitializer());
//绑定端口号
Channel channel = bootstrap.connect("127.0.0.1", 8992).sync().channel();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
while (true) {
channel.writeAndFlush(br.readLine() + "\r\n");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//异常发生退出
eventExecutors.shutdownGracefully();
}
}
}
public class ChatInitializer extends ChannelInitializer <SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
// pipeline.addLast(new DelimiterBasedFrameDecoder(4096, Delimiters.lineDelimiter()));
pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8), new StringEncoder(CharsetUtil.UTF_8));
pipeline.addLast(new ChatClientHandler());
}
}
public class ChatClientHandler extends SimpleChannelInboundHandler <String> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
System.out.println(msg);
}
}
服务器:
public class HeartbeatServer {
public static void main(String[] args) {
EventLoopGroup boosGrop = new NioEventLoopGroup();
EventLoopGroup workGrop = new NioEventLoopGroup();
ServerBootstrap serverBootstrap = new ServerBootstrap();
try {
serverBootstrap.group(boosGrop, workGrop).channel(NioServerSocketChannel.class).
childHandler(new HeartbeatInitlalizer()).handler(new LoggingHandler(LogLevel.INFO));
ChannelFuture channelFuture = serverBootstrap.bind(8992).sync();
ChannelFuture channelFuture1 = channelFuture.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
boosGrop.shutdownGracefully();
workGrop.shutdownGracefully();
}
}
}
public class HeartbeatInitlalizer extends ChannelInitializer <SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new IdleStateHandler(5, 6, 7, TimeUnit.SECONDS));
pipeline.addLast(new HeartbeatHandler());
}
}
public class HeartbeatHandler extends ChannelInboundHandlerAdapter {
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (evt instanceof IdleStateEvent) {
IdleStateEvent idleStateEvent = (IdleStateEvent) evt;
String eventType = null;
switch (idleStateEvent.state()) {
case ALL_IDLE:
eventType = "读写空闲";
break;
case WRITER_IDLE:
eventType = "写空闲";
break;
case READER_IDLE:
eventType = "读空闲";
break;
}
System.out.println(eventType);
ctx.channel().close();
}
}
}