2. Netty源码分析之使用篇

Posted lovezmc

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2. Netty源码分析之使用篇相关的知识,希望对你有一定的参考价值。

 

前言:在阅读Netty源码前,我们先了解下Netty的基本使用方法。

一、服务端代码

public class TimeServer 
    
    public static void main(String[] args) throws Exception 
        int port = 8080;
        if (args != null && args.length > 0) 
            try 
                port = Integer.valueOf(args[0]);
             catch (NumberFormatException e) 
                // 采用默认值
            
        
        new TimeServer().bind(port);
    
    
    public void bind(int port) throws Exception 
        // 配置服务端的NIO线程组
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try 
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup).channel(NioserverSocketChannel.class).option(ChannelOption.SO_BACKLOG, 1024)
                    .childHandler(new ChildChannelHandler());
            // 绑定端口,同步等待成功
            ChannelFuture f = b.bind(port).sync();

            // 等待服务端监听端口关闭
            f.channel().closeFuture().sync();
         finally 
            // 优雅退出,释放线程池资源
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        
    

    private class ChildChannelHandler extends ChannelInitializer<SocketChannel> 
        @Override
        protected void initChannel(SocketChannel arg0) throws Exception 
            arg0.pipeline().addLast(new TimeServerHandler());
        

    



public class TimeServerHandler extends ChannelHandlerAdapter 

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception 
        ByteBuf buf = (ByteBuf) msg;
        byte[] req = new byte[buf.readableBytes()];
        buf.readBytes(req);
        String body = new String(req, "UTF-8");
        System.out.println("The time server receive order : " + body);
        String currentTime = "QUERY TIME ORDER".equalsIgnoreCase(body)
                ? new java.util.Date(System.currentTimeMillis()).toString()
                : "BAD ORDER";
     // 创建UnpooledHeapByteBuf,同时设置对象的各个值(copy了一份byte数组放进buffer对象中) ByteBuf resp
= Unpooled.copiedBuffer(currentTime.getBytes()); ctx.write(resp); @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception ctx.flush(); @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) ctx.close();

二、客户端代码

public class TimeClient 
    public static void main(String[] args) throws Exception 
        int port = 8080;
        if (args != null && args.length > 0) 
            try 
                port = Integer.valueOf(args[0]);
             catch (NumberFormatException e) 
                // 采用默认值
            
        
        new TimeClient().connect(port, "127.0.0.1");
    

    public void connect(int port, String host) throws Exception 
        // 配置客户端NIO线程组
        EventLoopGroup group = new NioEventLoopGroup();
        try 
            Bootstrap b = new Bootstrap();
            b.group(group).channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true)
                    .handler(new ChannelInitializer<SocketChannel>() 
                        @Override
                        public void initChannel(SocketChannel ch) throws Exception 
                            ch.pipeline().addLast(new TimeClientHandler());
                        
                    );

            // 发起异步连接操作
            ChannelFuture f = b.connect(host, port).sync();

            // 当代客户端链路关闭
            f.channel().closeFuture().sync();
         finally 
            // 优雅退出,释放NIO线程组
            group.shutdownGracefully();
        
    



public class TimeClientHandler extends ChannelHandlerAdapter 
    private static final Logger logger = Logger.getLogger(TimeClientHandler.class.getName());
    private final ByteBuf firstMessage;

    /**
     * Creates a client-side handler.
     */
    public TimeClientHandler() 
        byte[] req = "QUERY TIME ORDER".getBytes();
        firstMessage = Unpooled.buffer(req.length);
        firstMessage.writeBytes(req);
    

    /**
     * 当客户端连接上服务端时,会触发ChannelActive(..)
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) 
        ctx.writeAndFlush(firstMessage);
    

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception 
        ByteBuf buf = (ByteBuf) msg;
        byte[] req = new byte[buf.readableBytes()];
        buf.readBytes(req);
        String body = new String(req, "UTF-8");
        System.out.println("Now is : " + body);
    

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) 
        // 释放资源
        logger.warning("Unexpected exception from downstream : " + cause.getMessage());
        ctx.close();
    

 

以上是关于2. Netty源码分析之使用篇的主要内容,如果未能解决你的问题,请参考以下文章

精尽 Netty 原理与源码专栏( 已经完成 61+ 篇,预计总共 70+ 篇 )

源码分析Netty4专栏

源码分析Netty4专栏

Netty源码分析之NioEventLoop执行流程

Netty源码分析之处理新连接

8. Netty源码分析之ByteBuf