这篇文章分析另外一个表重要比较基础的handler : ChannelInboundByteHandlerAdapter
当我们编写的服务器程序需要直接处理byte的时候,可以直接扩展它来实现inboundhandler,用于处理传送过来的byte数据。。。例如举一个典型的用法:
- public class MyChannelHandler extends ChannelInboundByteHandlerAdapter {
- @Override
- protected void inboundBufferUpdated(ChannelHandlerContext ctx, ByteBuf in)
- throws Exception {
- // TODO Auto-generated method stub
- //while (in.isReadable()) {
- //System.out.print((char)in.readByte());
- //}
- final String name = ctx.name();
- ByteBuf b = ctx.alloc().buffer(); //创建一个buffer用于存放数据
- b.writeBytes("aaa".getBytes());
- ctx.pipeline().write(b); //调用pipeline的write方法,将数据发送出去
- ctx.pipeline().flush().addListener(new ChannelFutureListener(){
- @Override
- public void operationComplete(ChannelFuture future)
- throws Exception {
- // TODO Auto-generated method stub
- System.out.println(name);
- future.channel().close().sync();
- }
- });
- }
- }
该类直接继承自ChannelInboundByteHandlerAdapter,然后实现了inboundBufferUpdated方法用于处理读取进来的数据。。。将这个类的对象加入到channel的pipeline上面之后,当这个channel已经有数据读进来之后会调用inboundBufferUpdated方法来处理。。。
我们首先还是来看一下ChannelInboundByteHandlerAdapter的继承体系:
ChannelInboundByteHandlerAdapter直接继承了ChannelStateHandlerAdapter,这个类型在上面的一篇文章中也有说明,它继承了stathandler接口,然后实现了里面的方法,不过这些方法实现的都很简单,无非是从当前pipeline上面向下寻找到另一个stathandler,调用相应的方法。。。
然后ChannelInboundByteHandlerAdapter还实现了ChannelInboundByteHandler接口,这个接口中多定义了一个方法,那就是discardInboundReadBytes。。。
好了,接下来我们来看看ChannelInboundByteHandlerAdapter的定义吧:
- public abstract class ChannelInboundByteHandlerAdapter
- extends ChannelStateHandlerAdapter implements ChannelInboundByteHandler {
- /**
- * Create a new unpooled {@link ByteBuf} by default. Sub-classes may override this to offer a more
- * optimized implementation.
- */
- @Override
- //用于构创建新的buffer
- public ByteBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception {
- return ChannelHandlerUtil.allocate(ctx);
- }
- @Override
- //抛弃已经读取的数据
- public void discardInboundReadBytes(ChannelHandlerContext ctx) throws Exception {
- ctx.inboundByteBuffer().discardSomeReadBytes();
- }
- @Override
- //当有新的收读取到时候,会调用过这个方法来处理这些读取到的数据
- public final void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception {
- inboundBufferUpdated(ctx, ctx.inboundByteBuffer());
- }
- /**
- * Callback which will get notifed once the given {@link ByteBuf} received more data to read. What will be done
- * with the data at this point is up to the implementation.
- * Implementations may choose to read it or just let it in the buffer to read it later.
- */
- //用户自己实现这个方法,真正的用于处理读取到的数据
- protected abstract void inboundBufferUpdated(ChannelHandlerContext ctx, ByteBuf in) throws Exception;
- }
public class DiscardClientHandler extends ChannelInboundByteHandlerAdapter {
private static final Logger logger = Logger.getLogger(
DiscardClientHandler.class.getName());
private final int messageSize;
private ByteBuf content;
private ChannelHandlerContext ctx;
public DiscardClientHandler(int messageSize) {
if (messageSize <= 0) {
throw new IllegalArgumentException(
"messageSize: " + messageSize);
}
this.messageSize = messageSize;
}
@Override
public void channelActive(ChannelHandlerContext ctx)
throws Exception {
this.ctx = ctx;
// Initialize the message.
content = ctx.alloc().directBuffer(messageSize).writeZero(messageSize);
// Send the initial messages.
generateTraffic();
}
@Override
public void inboundBufferUpdated(ChannelHandlerContext ctx, ByteBuf in)
throws Exception {
// Server is supposed to send nothing, but if it sends something, discard it.
in.clear();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx,
Throwable cause) throws Exception {
// Close the connection when an exception is raised.
logger.log(
Level.WARNING,
"Unexpected exception from downstream.",
cause);
ctx.close();
}
long counter;
private void generateTraffic() {
// Fill the outbound buffer up to 64KiB
ByteBuf out = ctx.nextOutboundByteBuffer();
while (out.readableBytes() < 65536) {
out.writeBytes(content, 0, content.readableBytes());
}
// Flush the outbound buffer to the socket.
// Once flushed, generate the same amount of traffic again.
ctx.flush().addListener(trafficGenerator);
}
private final ChannelFutureListener trafficGenerator = new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (future.isSuccess()) {
generateTraffic();
}
}
};
}
实现代码还是很简单,首先重载了newInboundBuffer方法,至于inboundBufferUpdated方法,其实是用来调用用户自定义的inboundBufferUpdated方法来来处理新进来的数据。。
因此用户编码的时候,只需要继承ChannelInboundByteHandlerAdapter类,然后实现inboundBufferUpdated方法就可以了。。。。