-
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。