2 chaobaby94 ChaoBaby94 于 2018.02.13 20:08 提问

Netty什么时候才是写空闲,还有pipeline中handler的执行顺序 5C
  1. netty什么时候是写空闲?
    客户端代码:
    // 写数据
    ChannelFuture cf = b.connect(HOST, PORT).sync();
    PkgEntity.Pkg.Builder builder = PkgEntity.Pkg.newBuilder();
    builder.setData("你好,服务器");
    builder.setReqType(0);
    PkgEntity.Pkg pkg = builder.build();
    cf.channel().writeAndFlush(pkg);
    cf.channel().closeFuture().sync();

        // 客户端心跳handler的代码
        userEventTriggered 方法中
        if(evt instanceof IdleStateEvent){
        IdleStateEvent event = (IdleStateEvent)evt;
    

    // if(event.state() == IdleState.ALL_IDLE){
    // if(idle_count > 3){
    // PkgEntity.Pkg.Builder builder = PkgEntity.Pkg.newBuilder();
    // builder.setReqType(1); // 1表示心跳数据
    // builder.setData("heartBeat");
    // Pkg pkg = builder.build();
    // ctx.writeAndFlush(pkg);
    // idle_count = -1;
    // }
    // idle_count++;
    // }
    if(event.state() == IdleState.WRITER_IDLE){ // 5秒没写
    System.out.println("写空闲");
    writer_idle_count++;
    if(writer_idle_count > 1){
    PkgEntity.Pkg.Builder builder = PkgEntity.Pkg.newBuilder();
    builder.setReqType(1); // 1表示心跳数据
    builder.setData("heartBeat");
    Pkg pkg = builder.build();
    ctx.writeAndFlush(pkg);
    }
    writer_idle_count = 0;
    } else if(event.state() == IdleState.READER_IDLE){ // 5秒没读
    System.out.println("读空闲");
    reader_idle_count++;
    if(reader_idle_count > 3){
    ctx.disconnect(); // disconnect和close的区别?
    }
    }
    } else{
    super.userEventTriggered(ctx, evt);
    }

    服务器端心跳handler方法
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    PkgEntity.Pkg pkg = (PkgEntity.Pkg)(msg);
    if(pkg.getReqType() == 0){  // 0 正常信息
        per_5_sec = 0;
        ctx.fireChannelRead(msg);
    } else if(pkg.getReqType() == 1){ // 收到客户端的心跳消息
        System.out.println(ctx.channel().remoteAddress()+"5秒没发送消息");
        if(per_5_sec >= 2){
            System.out.println(ctx.channel().remoteAddress()+"10秒没发送消息,关闭连接");
            ctx.close();
        } else{
            ReferenceCountUtil.release(msg);
        }
        per_5_sec++;
    }
    

    }

问题2:pipeline中handler的执行顺序
网上的都是inbound顺序,outbound逆序。但是我遇到过其他顺序也能执行成功的情况,而按照inbound顺序,outbound逆序却不行。
下面是可以成功执行的顺序:
Server:
ch.pipeline()

                // -- inbound顺序 -- 
                // 解码
                .addLast("frameDecoder", new MyProtobufVarint32FrameDecoder())
                .addLast("protobufDecoder", new MyProtobufDecoder(PkgEntity.Pkg.getDefaultInstance()))

                // 心跳
                .addLast("timeout", new HeartBeatServerHandler())     

                // -- outbound 逆序 --
                // 编码
                .addLast("protobufEncoder", new MyProtobufEncoder()) 
                .addLast("prepender",new MyProtobufVarint32LengthFieldPrepender())

                // -- 业务(inbound顺序) --
                // 业务
                .addLast("rcvHandler", new RcvHandler())
                .addLast("ackHandler", new AckHandler());

Client:
ch.pipeline()

                // 解码
                .addLast("protobufDecoder", new MyProtobufDecoder(PkgEntity.Pkg.getDefaultInstance()))
                .addLast("frameDecoder", new MyProtobufVarint32FrameDecoder())

                // 心跳
                .addLast("timeout", new IdleStateHandler(1,0,0,TimeUnit.SECONDS))
                .addLast(new HeartBeatClientHandler())

                // 编码
                .addLast("prepender",new MyProtobufVarint32LengthFieldPrepender())
                .addLast("protobufEncoder", new MyProtobufEncoder())

                // 业务
                .addLast("rcvHandler", new RcvHandler());

客户端编码顺序就是反过来的,先ProtobufDecoder,后ProtobufVarint32FrameDecoder。按道理应该是顺序,先后ProtobufVarint32FrameDecoder后先ProtobufDecoder。

1个回答

devmiao
devmiao   Ds   Rxr 2018.02.17 22:51
Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!