Netty由浅到深_第五章_Netty心跳检测机制案例

应用实例-群聊系统

  • 1)编写一个Netty心跳检测机制案例,当服务器超过3秒没有读取时,就会提示空闲
  • 2)当服务器超过5秒没有写操作时,就表示空闲
  • 3)实现当服务器超过7秒没有都或者写操作时,就提示读写空闲
package com.dd.netty.heartbeat;

import com.dd.netty.groupchat.GroupChatServer;
import com.dd.netty.groupchat.GroupChatServerHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
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.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleStateHandler;

import java.util.concurrent.TimeUnit;

public class MyServer {

    private int port ;//监听端口

    public MyServer(int port){
        this.port = port;
    }

    public void run() throws InterruptedException {
    //创建bossGroup和WrokerGroup
    NioEventLoopGroup bossGroup = new NioEventLoopGroup(1);
    NioEventLoopGroup workerGroup = new NioEventLoopGroup();//默认cpu核数乘以2个NioEventLoop
        try {
        ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap.group(bossGroup,workerGroup)
                .channel(NioServerSocketChannel.class)
                .handler(new LoggingHandler(LogLevel.INFO))//在boosGroup 增加一个日志处理器
                .option(ChannelOption.SO_BACKLOG,128)
                .childOption(ChannelOption.SO_KEEPALIVE,true)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {

                        ChannelPipeline pipeline = socketChannel.pipeline();

                        //加入Netty 提供的 IdleStateHandler
                        /*
                        * long readerIdleTime, 表示多长时间服务端没有读取客户端数据。就会发送一个心跳检测包,检测是否还是连接的状态
                        * long writerIdleTime,表示多长时间服务端没有写数据给客户端数据。就会发送一个心跳检测包,检测是否还是连接的状态
                        *  long allIdleTime, 表示多长时间服务端既没有写数据又没有读取数据给客户端数据。就会发送一个心跳检测包,检测是否还是连接的状态
                        * TimeUnit unit
                        *当IdleStateEvent事件触发后,就会传递给管道的下一个handler去处理,通过调用下一个handler的userEventTiggered方法处理
                        * IdleStateEvent(都空闲,写空闲,读写空闲)
                        * */
                        pipeline.addLast(new IdleStateHandler(3,5,7, TimeUnit.SECONDS));

                        //加入一个对空闲检测进一步处理的自定义handler
                        pipeline.addLast(new MyServerHandler());
                    }
                });

        System.out.println("Netty服务器启动");

        ChannelFuture chanelFuture = bootstrap.bind(port).sync();

        //监听关闭事件
        chanelFuture.channel().closeFuture().sync();
    }finally {
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
    }
}


    public static void main(String[] args) throws InterruptedException {
        new MyServer(7000).run();
    }
}

package com.dd.netty.heartbeat;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleStateEvent;

public class MyServerHandler extends ChannelInboundHandlerAdapter {

    /**
     *
     * @param ctx 上下文
     * @param evt 事件
     * @throws Exception
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent){

            //将evt向下转型到IdleStateEvent

            IdleStateEvent event = (IdleStateEvent)evt;

            String eventType =null;
            switch (event.state()){
                case READER_IDLE:
                    eventType = "读空闲";
                    break;
                case ALL_IDLE:
                    eventType="读写空闲";
                    break;
                case WRITER_IDLE:
                    eventType="写空闲";
                    break;
            }

            System.out.println(ctx.channel().remoteAddress()+"--超时事件--"+eventType);
            //接下来做相应处理

            //假如发生心跳事件  我们关闭通道  那么只会产生一次心跳
        }
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章