接上篇,本例中加有outhandler,先说明,本例是个不正常程序,只能用于理解
1)outhandler要放到inhandler之前,或者至少一个inhandler之前,否者outhadler.write不运行
package com.wang.netty4Out.first;
import org.apache.cassandra.cli.CliParser.newColumnFamily_return;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
/**
* 这个用于测试handler的传递功能
* @author wangzg
*
* 本例子使用的是 实现的handler中,各个函数都是先super,然后打印,除了handler1中的channelRead,这样打印出的顺序是,先2后1,也就是最后加进去的,先做,先进去的后做,跟
* 网上的不一致
*
* 本例子中各个handler中的方法,都在最后使用了super()的方法,顺序和网上的一致
*
* 本例子将用于数据解析
* 本例的例子是inhandler2 和inhandler3都发送了数据,但是客户断接收的时候,是连在一起的,因此这里需要想办法,也就是连包拆包
*
* 本例子发现个问题,在Inhandler中都可以使用ctx.writeAndflush(msg),但这样的做法会造成,如果有outhandler的时候,发送回客户端的数据,有多个
* outhandler发回的数据(都是一样的,个数是inhander中ctx.writeAndFlush()个数),如何解决的,既然需要msg向后传递,又不能
* 有多个重复数据发回,那就需要在inhandler的channelRead()不能使用super.channelread(),而是使用ctx.fireChannelRead(加工过的msg)
*/
public class WangNetty4Out1Server {
private static final Logger LOGGER = LoggerFactory.getLogger(WangNetty4Out1Server.class);
public void start(int port){
EventLoopGroup boss = new NioEventLoopGroup();
EventLoopGroup work = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap();
try {
bootstrap.group(boss, work)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 1024)
// .option(ChannelOption.SO_TIMEOUT, 5 * 1000)
.childOption(ChannelOption.SO_KEEPALIVE, true)
.childOption(ChannelOption.SO_RCVBUF, 10 * 1024)
.childOption(ChannelOption.SO_SNDBUF, 10 * 1024)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel sc) throws Exception {
sc.pipeline().addLast(new WangOuthandler1());
sc.pipeline().addLast(new WangInHandler1());
sc.pipeline().addLast(new WangInHandler2());
sc.pipeline().addLast(new WangInHandler3());
// sc.pipeline().addLast(new WangOuthandler1());
}
});
ChannelFuture future = bootstrap.bind(port).sync();
future.channel().closeFuture().sync();
} catch (Exception e) {
LOGGER.error("server 启动失败",e);
}finally{
boss.shutdownGracefully();
work.shutdownGracefully();
}
}
public static void main(String[] args) {
WangNetty4Out1Server server = new WangNetty4Out1Server();
server.start(8085);
}
}
package com.wang.netty4Out.first;
import org.apache.cassandra.utils.OutputHandler.SystemOutput;
import com.wang.netty4.six.NettyUtil;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
public class WangInHandler1 extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg)
throws Exception {
// TODO Auto-generated method stub
System.out.println(" WangInHandler1 channelRead");
System.out.println(" WangInHandler1 receive:"+NettyUtil.parseByteBufMsg(msg));
ctx.fireChannelRead(msg);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
System.out.println(" WangInHandler1 channelReadComplete");
super.channelReadComplete(ctx);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
throws Exception {
// TODO Auto-generated method stub
System.out.println(" WangInHandler1 exceptionCaught");
super.exceptionCaught(ctx, cause);
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
System.out.println(" WangInHandler1 channelActive");
super.channelActive(ctx);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
System.out.println(" WangInHandler1 channelInactive");
super.channelInactive(ctx);
}
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
System.out.println(" WangInHandler1 channelRegistered");
super.channelRegistered(ctx);
}
@Override
public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
System.out.println(" WangInHandler1 channelUnregistered");
super.channelUnregistered(ctx);
}
@Override
public void channelWritabilityChanged(ChannelHandlerContext ctx)
throws Exception {
// TODO Auto-generated method stub
System.out.println(" WangInHandler1 channelWritabilityChanged");
super.channelWritabilityChanged(ctx);
}
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt)
throws Exception {
// TODO Auto-generated method stub
System.out.println(" WangInHandler1 userEventTriggered");
super.userEventTriggered(ctx, evt);
}
}
package com.wang.netty4Out.first;
import com.wang.netty4.six.NettyUtil;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
public class WangInHandler2 extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg)
throws Exception {
// TODO Auto-generated method stub
System.out.println(" WangInHandler2 channelRead");
System.out.println(" WangInHandler2 receive:"+NettyUtil.parseByteBufMsg(msg));
ctx.writeAndFlush(NettyUtil.packageStringToByteBuf("I am handler2"));
// ctx.write(NettyUtil.packageStringToByteBuf(" I am inhandler2"));
super.channelRead(ctx, msg);
// ctx.fireChannelRead(NettyUtil.packageStringToByteBuf("aaaaaaa"));
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
System.out.println(" WangInHandler2 channelReadComplete");
super.channelReadComplete(ctx);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
throws Exception {
// TODO Auto-generated method stub
System.out.println(" WangInHandler2 exceptionCaught");
super.exceptionCaught(ctx, cause);
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
System.out.println(" WangInHandler2 channelActive");
super.channelActive(ctx);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
System.out.println(" WangInHandler2 channelInactive");
super.channelInactive(ctx);
}
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
System.out.println(" WangInHandler2 channelRegistered");
super.channelRegistered(ctx);
}
@Override
public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
System.out.println(" WangInHandler2 channelUnregistered");
super.channelUnregistered(ctx);
}
@Override
public void channelWritabilityChanged(ChannelHandlerContext ctx)
throws Exception {
// TODO Auto-generated method stub
System.out.println(" WangInHandler2 channelWritabilityChanged");
super.channelWritabilityChanged(ctx);
}
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt)
throws Exception {
// TODO Auto-generated method stub
System.out.println(" WangInHandler2 userEventTriggered");
super.userEventTriggered(ctx, evt);
}
}
package com.wang.netty4Out.first;
import com.wang.netty4.six.NettyUtil;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
public class WangInHandler3 extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg)
throws Exception {
// TODO Auto-generated method stub
// super.channelRead(ctx, msg);
System.out.println(" WangInHandler3 channelRead");
ctx.writeAndFlush(NettyUtil.packageStringToByteBuf(" I am inHandler3"));
// ctx.writeAndFlush(msg);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
System.out.println(" WangInHandler3 channelReadComplete");
super.channelReadComplete(ctx);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
throws Exception {
// TODO Auto-generated method stub
System.out.println(" WangInHandler3 exceptionCaught");
super.exceptionCaught(ctx, cause);
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
System.out.println(" WangInHandler3 channelActive");
super.channelActive(ctx);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
System.out.println(" WangInHandler3 channelInactive");
super.channelInactive(ctx);
}
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
System.out.println(" WangInHandler3 channelRegistered");
super.channelRegistered(ctx);
}
@Override
public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
System.out.println(" WangInHandler3 channelUnregistered");
super.channelUnregistered(ctx);
}
@Override
public void channelWritabilityChanged(ChannelHandlerContext ctx)
throws Exception {
// TODO Auto-generated method stub
System.out.println(" WangInHandler3 channelWritabilityChanged");
super.channelWritabilityChanged(ctx);
}
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt)
throws Exception {
// TODO Auto-generated method stub
System.out.println(" WangInHandler3 userEventTriggered");
super.userEventTriggered(ctx, evt);
}
}
运行结果
服务端
WangInHandler1 channelRegistered
WangInHandler2 channelRegistered
WangInHandler3 channelRegistered
WangInHandler1 channelActive
WangInHandler2 channelActive
WangInHandler3 channelActive
WangOuthandler1 read
WangInHandler1 channelRead
WangInHandler1 receive:Are you ok?
WangInHandler2 channelRead
WangInHandler2 receive:
WangOuthandler1 write
WangOuthandler1 receive I am handler2
WangOuthandler1 flush
WangInHandler3 channelRead
WangOuthandler1 write
WangOuthandler1 receive I am inHandler3
WangOuthandler1 flush
WangInHandler1 channelReadComplete
WangInHandler2 channelReadComplete
WangInHandler3 channelReadComplete
WangOuthandler1 read
客户断
channelActive
ctx.channel().localAddress():/192.168.1.31:58072
channelRead
Server said:WangOuthandler1WangOuthandler1
大家可以看到我的客户端接收到了2个WangOuthandler1,原因是Inhandler2和inhandler3都ctx.writeandflush()的原因,同时还有indhandler2的super.channelRead(ctx, msg);
在看服务端,由于我的outhandler放在了inhandler之前,因此WangOuthandler1 read WangInHandler1 channelRead,
同时因为inhandler2的super原因,outhandler1.write第一次接收到了数据,进行写操作,发送给客户端,inhandler3的writeandflush(),再次进入outhandler.write()操作,发送给客户端,因此客户端收到了2个数据WangOuthandler1,因此当inhandler中每一次ctx.write()或这ctx.writeandflush,outhandler1都会发送给客户端,只有使用ctx.firechannelread,不会触发outhandler操作