Netty--心跳

BtWangZhi發表於2017-10-05

1 學習IdleStateHandler用來檢測會話狀態。
對於服務端,可以定時清除閒置會話。
對於客戶端來說,檢測會話是否斷開,是否重連,用來檢測網路延遲。
Netty3,觸發的是handleUpstream方法:

// 設定管道工廠
        bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
            public ChannelPipeline getPipeline() throws Exception {
                ChannelPipeline pipeline = Channels.pipeline();

                //設定下線時間。第二個引數規定指定的秒數內沒有讀操作時將觸發事件,第三個引數規定指定的秒數內沒有寫操作時將觸發事件,
                //均會觸發ServerHandler-》中的handleUpstream
                pipeline.addLast("idle", new IdleStateHandler(hashedWheelTimer, 5, 5, 10));

                // 在此處設定後在messageReceived中將不需要轉換
                pipeline.addLast("decoder", new StringDecoder());
                // 傳送資料時不需要轉換
                pipeline.addLast("encoder", new StringEncoder());
                // 業務處理物件
                pipeline.addLast("helloHandler", new ServerHandler());
                return pipeline;
            }
        });
public class ServerHandler extends SimpleChannelHandler {

    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
            throws Exception {
        System.out.println(e.getMessage());
    }

    @Override
    public void handleUpstream(final ChannelHandlerContext ctx, ChannelEvent e)
            throws Exception {
        if (e instanceof IdleStateEvent) {
            if(((IdleStateEvent)e).getState()==IdleState.ALL_IDLE){
                //關閉會話,替玩家下線
                ChannelFuture write=ctx.getChannel().write("time out,you will close");
                write.addListener(new ChannelFutureListener() {
                    /**
                     * IO操作執行完回撥
                     */
                    public void operationComplete(ChannelFuture future) throws Exception {
                        // TODO Auto-generated method stub
                        ctx.getChannel().close();
                    }
                });

                System.out.println("替玩家下線。。。");
                ctx.getChannel().close();
            }

            IdleStateEvent event = (IdleStateEvent) e;
            System.out.println(event.getState()+"  ");
        } else {
            super.handleUpstream(ctx, e);
        }
    }
}

Netty5,觸發的是userEventTriggered方法:

// 設定管道工廠
            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 ServerHandler());
                }
            });

觸發的事件

/**
 * 服務端訊息處理
 * 
 * @author Tang
 *
 */
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) {
                // 向客戶端傳送資料
                ChannelFuture writeAndFlush = ctx
                        .writeAndFlush("you will close");
                writeAndFlush
                        .addListener(new GenericFutureListener<Future<? super Void>>() {
                            public void operationComplete(
                                    Future<? super Void> future)
                                    throws Exception {
                                // 關閉會話
                                ctx.channel().close();
                            }
                        });
            }
        }
    }

通過設定時間,當一個連線超過這個時間沒有連線時將觸發userEventTriggered方法。

相關文章