netty3 & netty5心跳对比

版权声明:版权为ZZQ所有 https://blog.csdn.net/qq_39148187/article/details/81603105

心跳对于server来说可以定时的检测客户端是否存在清除闲置的链接

对于client 来说可以检测和服务器的链接是否中断,测试延迟,首先分析netty3 的心跳代码, netty3 和netty5 有一定的差异, netty5的封装度高

netty3

netty的心跳检测的核心类是 IdleStateEvent  ,这个对象在netty3 中可以通过回掉函数handleUpstream 传递的 ChannelEvent 进行转换,通过getstate 方法可以返回心跳的状态 ,代码如下


package heartbeat;



import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.*;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;
import org.jboss.netty.handler.timeout.IdleState;
import org.jboss.netty.handler.timeout.IdleStateEvent;
import org.jboss.netty.handler.timeout.IdleStateHandler;
import org.jboss.netty.util.HashedWheelTimer;

import java.net.InetSocketAddress;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author ZZQ
 * @date 2018/8/11 20:16
 */
public class Server {

    /**
    *   @author ZZQ
    *   @date 2018/8/11
    *   @description  服务器的心跳处理可以检测客户端是否存在,清理僵尸客户端
     *                  客户端的心跳可以检测和服务器是否链接
    */
    public static void main(String[] args) {
        ServerBootstrap bootstrap = new ServerBootstrap();

        ExecutorService worker = Executors.newCachedThreadPool();
        ExecutorService boss = Executors.newCachedThreadPool();

        HashedWheelTimer hashedWheelTimer = new HashedWheelTimer();
        //设置线程工厂
        bootstrap.setFactory(new NioServerSocketChannelFactory(boss,worker));

        bootstrap.setPipelineFactory(()->{
            ChannelPipeline pipeline = Channels.pipeline();
            pipeline.addLast("idle", new IdleStateHandler(hashedWheelTimer, 5, 5, 10));
            pipeline.addLast("decoder", new StringDecoder());
            pipeline.addLast("encoder", new StringEncoder());
            pipeline.addLast("helloHandler", new HelloHandler());
            return pipeline;
        });

        bootstrap.bind(new InetSocketAddress(8888));


        System.out.println("start...");
    }


    static  class  HelloHandler extends SimpleChannelHandler{

        /**
        *   @author ZZQ
        *   @date 2018/8/11
        *   @description   此回掉函数管理心跳事件
        */
        @Override
        public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
            if(e instanceof  IdleStateEvent) {
                IdleState state = ((IdleStateEvent) e).getState();
                if (state == IdleState.ALL_IDLE) {
                    System.out.println("提醒玩家下线");
                    ChannelFuture future = ctx.getChannel().write("time out ,you will close");
                    future.addListener((x) -> {
                        ctx.getChannel().close();
                    });
                }
            }else {
                super.handleUpstream(ctx,e);
            }
        }
    }
}

使用心跳回掉函数的之前在初始化管道工厂的时候要加入, 心跳函数的调用时间周期

  pipeline.addLast("idle", new IdleStateHandler(hashedWheelTimer, 5, 5, 10));

netty5

netty5 废除了netty3 中的handleupstream方法, 提供userEventTriggered 这个回掉函数

源码上的说明, 如果一个用户事件被触发, 函数被调用 , 由此可知不止一个事件  代码如下

package com.zzq.Heartbeat;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
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.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.handler.timeout.IdleStateHandler;

import java.net.InetAddress;

/**
 * @author ZZQ
 * @date 2018/8/11 16:54
 */
public class Server {

    public static void main(String[] args) {
        //创建服务类
        ServerBootstrap bootstrap = new ServerBootstrap() ;
        //创建线程池
        EventLoopGroup worker = new NioEventLoopGroup();
        EventLoopGroup boss = new NioEventLoopGroup() ;
        //设置线程池
        bootstrap.group(boss,worker);
        bootstrap.channel(NioServerSocketChannel.class);
        //设置通道
        bootstrap.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 MyHandler());
            }
        });

    bootstrap.bind(8888);


    }

    static  class MyHandler extends  SimpleChannelInboundHandler{

        @Override
        protected void messageReceived(ChannelHandlerContext ctx, Object msg) throws Exception {
            System.out.println(msg);
        }

        @Override
        public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
            IdleStateEvent idleStateEvent = (IdleStateEvent) evt;
            if(idleStateEvent.state() == IdleState.ALL_IDLE){
                ChannelFuture future = ctx.writeAndFlush("会话超时...");
                future.addListener((x)->{
                    ctx.channel().close();
                });

            }
        }
    }
}

netty 是一款异步的事件驱动的网络应用程序框架, 支持快速的开发和可维护的高性能面向协议的服务器和客户端

猜你喜欢

转载自blog.csdn.net/qq_39148187/article/details/81603105