Netty笔记(七)ChannelHandlers and Codes 整合

    Netty 提供了ChannelHandler接口,还有用于Codes的ChannelHandler子接口。通过组合搭配, 灵活的构建我们需要的应用。

    SSL / TSL 服务

搭建SSL/TSL,Java EE 规范提供了 SSLContext 跟 SSLEngine接口,加之Netty为我们实现了一个SSLHandler,可以容易的实现。

其过程:

Netty笔记(七)ChannelHandlers and Codes 整合

示例代码:


public class SslChannelInitializer extends ChannelInitializer<Channel>
{
    private final SSLContext context;
    private final boolean client;
    private final boolean startTls;

    public SslChannelInitializer( SSLContext context, boolean client, boolean startTls )
    {
        this.context = context;
        this.client = client;
        this.startTls = startTls;
    }
    
    @Override
    protected void initChannel( Channel ch ) throws Exception
    {
        SSLEngine engine = context.createSSLEngine();
        engine.setUseClientMode( client );
        ch.pipeline().addFirst( "ssl" , new SslHandler(engine, startTls));
    }
}


   

    Http 服务

实现支持Http服务,需要几个Codes

HttpRequestEncoder、HttpResponseEncoder、HttpRequestDecoder、HttpResponseDecoder

示例代码:


public class HttpDecoderEncoderInitializer extends ChannelInitializer<Channel>
{

    private final boolean client;

    public HttpDecoderEncoderInitializer( boolean client )
    {
        this.client = client;
    }

    @Override
    protected void initChannel( Channel ch ) throws Exception
    {
        ChannelPipeline channelPipeline = ch.pipeline();
        if ( client )
        {
            channelPipeline.addLast( "decoder", new HttpResponseDecoder() );
            channelPipeline.addLast( "encoder", new HttpRequestEncoder() );
            //or
            //channelPipeline.addLast( "codes", new HttpServerCodec() );
        }
        else
        {
            channelPipeline.addLast( "decoder", new HttpRequestDecoder() );
            channelPipeline.addLast( "encoder", new HttpRequestEncoder() );
            //or
            //channelPipeline.addLast( "codes", new HttpClientCodec() );
        }
    }

}
    对于分段的Http信息,使用HttpObjectAggregator



public class HttpAggregatorInitializer extends ChannelInitializer<Channel>
{

    private final boolean client;

    public HttpAggregatorInitializer( boolean client )
    {
        this.client = client;
    }

    @Override
    protected void initChannel( Channel ch ) throws Exception
    {
        ChannelPipeline channelPipeline = ch.pipeline();
        if ( client )
        {
            channelPipeline.addLast( "codes", new HttpClientCodec() );
        }
        else
        {
            channelPipeline.addLast( "codes", new HttpServerCodec() );
        }
        /*
         * if message is getting bigger , raise a TooLongFrameException is thrown
         */
        channelPipeline.addLast( "aggegator", new HttpObjectAggregator( 1024 * 512 ) );
    }
}
    对于压缩的数据。



public class HttpCompressionInitializer extends ChannelInitializer<Channel>
{
    private final boolean client;
    public HttpCompressionInitializer( boolean client )
    {
        this.client = client;
    }

    @Override
    protected void initChannel( Channel ch ) throws Exception
    {
        ChannelPipeline pipeline = ch.pipeline();
        if ( client )
        {
            pipeline.addLast( "codes", new HttpClientCodec() );
            pipeline.addLast( "decompressor", new HttpContentDecompressor() );
        }
        else
        {
            pipeline.addLast( "codes", new HttpServerCodec() );
            pipeline.addLast( "compressor", new HttpContentCompressor() );
        }
    }
}


    Https  服务。


public class HttpsCodecInitializer extends ChannelInitializer<Channel>
{

    private final SSLContext context;
    private final boolean client;

    public HttpsCodecInitializer( SSLContext context, boolean client )
    {
        this.context = context;
        this.client = client;
    }

    @Override
    protected void initChannel( Channel ch ) throws Exception
    {
        SSLEngine engine = context.createSSLEngine();
        engine.setUseClientMode( client );

        ChannelPipeline pipeline = ch.pipeline();
        pipeline.addFirst( "ssl", new SslHandler( engine ) );
        if ( client )
        {
            pipeline.addLast( "codes", new HttpClientCodec() );
        }
        else
        {
            pipeline.addLast( "codes", new HttpServerCodec() );
        }
    }

}



处理心跳跟连接超时

IdleStateHandler : 当连接空闲状态到达超时时间,触发事件,且事件源为IdleStateEvent

ReadTimeoutHandler    : 读数据超时,抛出ReadTimeoutException

WriteTimeoutHandler    :写数据超时,抛出WriteTimeoutException

例子代码:


public class IdleStateHandlerInitializer extends ChannelInitializer<Channel>
{

    @Override
    protected void initChannel( Channel ch ) throws Exception
    {
        ChannelPipeline channelPipeline = ch.pipeline();
        channelPipeline.addLast( new IdleStateHandler( 0, 0, 60, TimeUnit.SECONDS ) );
        channelPipeline.addLast( new HeadbeatHandler() );
    }

    private static final class HeadbeatHandler extends ChannelInboundHandlerAdapter
    {

        private static final ByteBuf HEARTBEAT_SEQUENCE = Unpooled.unreleasableBuffer(
                Unpooled.copiedBuffer( "HEARTBEAT", CharsetUtil.ISO_8859_1 ) );

        @Override
        public void userEventTriggered( ChannelHandlerContext ctx, Object evt ) throws Exception
        {
            if ( evt instanceof IdleStateEvent )
            {
                ctx.writeAndFlush( HEARTBEAT_SEQUENCE.duplicate() )//
                        .addListener( ChannelFutureListener.CLOSE_ON_FAILURE );
            }
            else
            {
                super.userEventTriggered( ctx, evt );
            }
        }

    }

}



关于定界符的协议

DelimiterBasedFameDecoder : 根据定界符抽取数据片段的解码器

LineBasedFrameDecoder:基于行片段的解码器,用于\r\n定界符分行。



public class LineBasedHandlerInitializer extends ChannelInitializer<Channel>
{

    @Override
    protected void initChannel( Channel ch ) throws Exception
    {
        ChannelPipeline channelPipeline = ch.pipeline();
        channelPipeline.addLast( new LineBasedFrameDecoder( 65 * 1024 ) );
        channelPipeline.addLast( new FrameHandler());
    }
    
    private static final class FrameHandler extends  SimpleChannelInboundHandler<ByteBuf>
    {
        @Override
        protected void channelRead0( ChannelHandlerContext ctx, ByteBuf msg ) throws Exception
        {
            // do something
        }
    }

}
扩展例子:



public class CmdHandlerInitializer extends ChannelInitializer<Channel>
{

    private static class Cmd
    {

        private final ByteBuf name;
        private final ByteBuf args;

        public Cmd( ByteBuf name, ByteBuf args )
        {
            this.name = name;
            this.args = args;
        }
    }

    private static class ComDecoder extends LineBasedFrameDecoder
    {

        public ComDecoder( int maxLength )
        {
            super( maxLength );
        }

        @Override
        protected Object decode( ChannelHandlerContext ctx, ByteBuf buffer ) throws Exception
        {
            ByteBuf frame = (ByteBuf) super.decode( ctx, buffer );
            if ( frame == null )
            {
                return null;
            }

            int index = frame.indexOf( frame.readerIndex(), frame.writerIndex(), (byte) ' ' );
            return new Cmd( frame.slice( frame.readerIndex(), index ), frame.slice( index + 1, frame.writerIndex() ) );
        }
    }

    public static class CmdHandler extends SimpleChannelInboundHandler<Cmd>
    {
        @Override
        protected void channelRead0( ChannelHandlerContext ctx, Cmd msg ) throws Exception
        {
            // do something
        }
    }

    @Override
    protected void initChannel( Channel ch ) throws Exception
    {
        ch.pipeline().addLast( new ComDecoder( 65 * 1024 ) );
        ch.pipeline().addLast( new CmdHandler() );
    }

}


关于约定长度的协议处理

FixedLengthFrameDecoder : 抽取固定的字节长度,形成一个Frame

Netty笔记(七)ChannelHandlers and Codes 整合

LengthFieldBasedFrameDecoder : 抽取信息头设置长度,划分为不同的Frame


Netty笔记(七)ChannelHandlers and Codes 整合


public class LengthBasedInitializer extends ChannelInitializer<Channel>
{

    @Override
    protected void initChannel( Channel ch ) throws Exception
    {
        ChannelPipeline channelPipeline = ch.pipeline();
        channelPipeline.addLast( new LengthFieldBasedFrameDecoder(65*1024, 0, 8));
        channelPipeline.addLast( new FrameHandler());
    }
    
    private static class FrameHandler extends  SimpleChannelInboundHandler<ByteBuf>
    {
        @Override
        protected void channelRead0( ChannelHandlerContext ctx, ByteBuf msg ) throws Exception
        {
            // todo something
        }
    }

}




写大数据

Netty允许写数据,使用 zero-memory-zero 方式。 对javaAPI进行的封装,处理了很多细节。

提供了一个分块处理的ChunkedWriterHandler


public class ChunkedWriteHandlerInitializer extends ChannelInitializer<Channel>
{

    private final File file;

    public ChunkedWriteHandlerInitializer( File file )
    {
        this.file = file;
    }

    @Override
    protected void initChannel( Channel ch ) throws Exception
    {
        ChannelPipeline channelPipeline = ch.pipeline();
        channelPipeline.addLast( new ChunkedWriteHandler() );
        channelPipeline.addLast( new WriteStreamHandler() );
    }

    private class WriteStreamHandler extends ChannelInboundHandlerAdapter
    {

        @Override
        public void channelActive( ChannelHandlerContext ctx ) throws Exception
        {
            super.channelActive( ctx );
            ctx.writeAndFlush( new ChunkedStream(
                    new FileInputStream( ChunkedWriteHandlerInitializer.this.file ) ) );
        }
    }

}
传java对象序列化数据


使用JDK序列化,Netty提供了

CompatibleObjectDecoder、CompatibleObjectEncoder、

CompactObjectDecoder、CompactObjectEncoder

使用Jboss的Marshalling, Netty提供了

CompatibleMarshallingDecoder、CompatibleMarshallingEncoder

MarshallingDecoder、MarshallingEncoder

public class MarshallingInitializer extends ChannelInitializer<Channel>
{

    private final MarshallerProvider marshallerProvider;
    private final UnmarshallerProvider unmarshallerProvider;

    public MarshallingInitializer( MarshallerProvider marshallerProvider, UnmarshallerProvider unmarshallerProvider )
    {
        this.marshallerProvider = marshallerProvider;
        this.unmarshallerProvider = unmarshallerProvider;
    }

    @Override
    protected void initChannel( Channel ch ) throws Exception
    {

        ChannelPipeline pipeline = ch.pipeline();
        pipeline.addLast( new MarshallingDecoder( unmarshallerProvider ) );
        pipeline.addLast( new MarshallingEncoder( marshallerProvider ) );
        pipeline.addLast( new ObjectHandler() );
    }

    private static class ObjectHandler extends SimpleChannelInboundHandler<Serializable>
    {
        @Override
        protected void channelRead0( ChannelHandlerContext ctx, Serializable msg ) throws Exception
        {
            // do somethod
        }
    }
}




你可能感兴趣的:(Netty笔记(七)ChannelHandlers and Codes 整合)