接上篇
先总结,网上都说的是inhandler是顺序进入pipeline(),顺序解析,但没有说1hanlder解析完如何传递给下一个,
outhandler是顺序进入pipeline(),逆序出来,但没有说逆序的时候如何传递给下一个outhanler
inhandler使用ctx.fireChannelRead(msg),传递给下一个inhandler,
outhandler使用ctx.write(msg,promise)传递给下一个outhandler
所有的inhandler的最后一个使用ctx.writeAndFlush(msg)触发给outhandler
所有的outhandler的出去口,使用ctx.writeAndFlush(msg)发送给客户端
例子
package com.wang.netty4Out.third;
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)
* 每一次inhandler的super()或者ctx.firechannelread,操作触发outhandler的write()操作和下一个inhandler的channelread操作,每一次
* inhandler的ctx.write()操作,触发outhandler的write()中的ctx.write()操作
*/
public class WangNetty4Out3Server {
private static final Logger LOGGER = LoggerFactory.getLogger(WangNetty4Out3Server.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 WangOuthandler2());
sc.pipeline().addLast(new WangOuthandler3());
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) {
WangNetty4Out3Server server = new WangNetty4Out3Server();
server.start(8085);
}
}
package com.wang.netty4Out.third;
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.third;
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.fireChannelRead(NettyUtil.packageStringToByteBuf("I am handler2"));
}
@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.third;
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
System.out.println(" WangInHandler3 channelRead");
System.out.println("WangInHandler3 channelRead receive:"+NettyUtil.parseByteBufMsg(msg));
ctx.writeAndFlush(NettyUtil.packageStringToByteBuf(" I am inHandler3"));//最后一个indhandler需要ctx.write()而不能使用下面2行
}
@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);
}
}
package com.wang.netty4Out.third;
import java.net.SocketAddress;
import com.wang.netty4.six.NettyUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPromise;
public class WangOuthandler1 extends ChannelOutboundHandlerAdapter{
@Override
public void bind(ChannelHandlerContext ctx, SocketAddress localAddress,ChannelPromise promise) throws Exception {
System.out.println(" WangOuthandler1 bind localAddress:"+localAddress.toString());
super.bind(ctx, localAddress, promise);
}
@Override
public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress,SocketAddress localAddress, ChannelPromise promise)throws Exception {
System.out.println(" WangOuthandler1 connect remoteAddress:"+remoteAddress.toString()+" localAddress:"+localAddress.toString());
super.connect(ctx, remoteAddress, localAddress, promise);
}
@Override
public void disconnect(ChannelHandlerContext ctx, ChannelPromise promise)
throws Exception {
System.out.println(" WangOuthandler1 ctx");
super.disconnect(ctx, promise);
}
public void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {
System.out.println(" WangOuthandler1 close");
super.close(ctx, promise);
}
@Override
public void deregister(ChannelHandlerContext ctx, ChannelPromise promise)
throws Exception {
System.out.println(" WangOuthandler1 deregister");
super.deregister(ctx, promise);
}
public void read(ChannelHandlerContext ctx) throws Exception {
System.out.println(" WangOuthandler1 read");
super.read(ctx);
}
@Override
public void write(ChannelHandlerContext ctx, Object msg,
ChannelPromise promise) throws Exception {
System.out.println(" WangOuthandler1 write");
System.out.println("WangOuthandler1 receive " +NettyUtil.parseByteBufMsg(msg));
System.out.println("WangOuthandler1 send WangOuthandler1");
ctx.writeAndFlush(NettyUtil.packageStringToByteBuf("WangOuthandler1"));
// super.write(ctx, msg, promise);
}
public void flush(ChannelHandlerContext ctx) throws Exception {
System.out.println(" WangOuthandler1 flush");
super.flush(ctx);
}
}
package com.wang.netty4Out.third;
import java.net.SocketAddress;
import com.wang.netty4.six.NettyUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPromise;
public class WangOuthandler2 extends ChannelOutboundHandlerAdapter{
@Override
public void bind(ChannelHandlerContext ctx, SocketAddress localAddress,ChannelPromise promise) throws Exception {
System.out.println(" WangOuthandler2 bind localAddress:"+localAddress.toString());
super.bind(ctx, localAddress, promise);
}
@Override
public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress,SocketAddress localAddress, ChannelPromise promise)throws Exception {
System.out.println(" WangOuthandler2 connect remoteAddress:"+remoteAddress.toString()+" localAddress:"+localAddress.toString());
super.connect(ctx, remoteAddress, localAddress, promise);
}
@Override
public void disconnect(ChannelHandlerContext ctx, ChannelPromise promise)
throws Exception {
System.out.println(" WangOuthandler2 ctx");
super.disconnect(ctx, promise);
}
public void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {
System.out.println(" WangOuthandler2 close");
super.close(ctx, promise);
}
@Override
public void deregister(ChannelHandlerContext ctx, ChannelPromise promise)
throws Exception {
System.out.println(" WangOuthandler2 deregister");
super.deregister(ctx, promise);
}
public void read(ChannelHandlerContext ctx) throws Exception {
System.out.println(" WangOuthandler2 read");
super.read(ctx);
}
@Override
public void write(ChannelHandlerContext ctx, Object msg,
ChannelPromise promise) throws Exception {
System.out.println(" WangOuthandler2 write");
System.out.println("WangOuthandler2 receive " +NettyUtil.parseByteBufMsg(msg));
// ctx.writeAndFlush(NettyUtil.packageStringToByteBuf("WangOuthandler2"));
System.out.println("WangOuthandler2 send WangOuthandler2");
ctx.write(NettyUtil.packageStringToByteBuf("WangOuthandler2"), promise);
// super.write(ctx, msg, promise);
}
public void flush(ChannelHandlerContext ctx) throws Exception {
System.out.println(" WangOuthandler2 flush");
super.flush(ctx);
}
}
package com.wang.netty4Out.third;
import java.net.SocketAddress;
import com.wang.netty4.six.NettyUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPromise;
public class WangOuthandler3 extends ChannelOutboundHandlerAdapter{
@Override
public void bind(ChannelHandlerContext ctx, SocketAddress localAddress,ChannelPromise promise) throws Exception {
System.out.println(" WangOuthandler3 bind localAddress:"+localAddress.toString());
super.bind(ctx, localAddress, promise);
}
@Override
public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress,SocketAddress localAddress, ChannelPromise promise)throws Exception {
System.out.println(" WangOuthandler3 connect remoteAddress:"+remoteAddress.toString()+" localAddress:"+localAddress.toString());
super.connect(ctx, remoteAddress, localAddress, promise);
}
@Override
public void disconnect(ChannelHandlerContext ctx, ChannelPromise promise)
throws Exception {
System.out.println(" WangOuthandler3 ctx");
super.disconnect(ctx, promise);
}
public void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {
System.out.println(" WangOuthandler3 close");
super.close(ctx, promise);
}
@Override
public void deregister(ChannelHandlerContext ctx, ChannelPromise promise)
throws Exception {
System.out.println(" WangOuthandler3 deregister");
super.deregister(ctx, promise);
}
public void read(ChannelHandlerContext ctx) throws Exception {
System.out.println(" WangOuthandler3 read");
super.read(ctx);
}
@Override
public void write(ChannelHandlerContext ctx, Object msg,
ChannelPromise promise) throws Exception {
System.out.println(" WangOuthandler3 write");
System.out.println("WangOuthandler3 receive " +NettyUtil.parseByteBufMsg(msg));
System.out.println("WangOuthandler3 send WangOuthandler3");
// ctx.writeAndFlush(NettyUtil.packageStringToByteBuf("WangOuthandler3"));
ctx.write(NettyUtil.packageStringToByteBuf("WangOuthandler3"), promise);
// super.write(ctx, msg, promise);
}
public void flush(ChannelHandlerContext ctx) throws Exception {
System.out.println(" WangOuthandler3 flush");
super.flush(ctx);
}
}
服务端运行结果
WangInHandler1 channelRegistered
WangInHandler2 channelRegistered
WangInHandler3 channelRegistered
WangInHandler1 channelActive
WangInHandler2 channelActive
WangInHandler3 channelActive
WangOuthandler3 read
WangOuthandler2 read
WangOuthandler1 read
WangInHandler1 channelRead
WangInHandler1 receive:Are you ok?
WangInHandler2 channelRead
WangInHandler2 receive:
WangInHandler3 channelRead
WangInHandler3 channelRead receive:I am handler2
WangOuthandler3 write
WangOuthandler3 receive I am inHandler3
WangOuthandler3 send WangOuthandler3
WangOuthandler2 write
WangOuthandler2 receive WangOuthandler3
WangOuthandler2 send WangOuthandler2
WangOuthandler1 write
WangOuthandler1 receive WangOuthandler2
WangOuthandler1 send WangOuthandler1
WangOuthandler3 flush
WangOuthandler2 flush
WangOuthandler1 flush
WangInHandler1 channelReadComplete
WangInHandler2 channelReadComplete
WangInHandler3 channelReadComplete
WangOuthandler3 read
WangOuthandler2 read
WangOuthandler1 read
客户断运行结果
channelActive
ctx.channel().localAddress():/192.168.1.31:58971
channelRead
Server said:WangOuthandler1
可以看到和我们预想的一样,客户端只收到一次返回,而服务断通过
WangInHandler1 channelRead
WangInHandler2 channelRead
WangInHandler3 channelRead
WangOuthandler3 write
WangOuthandler2 write
WangOuthandler1 write
的方式进行数据解析、发送