【Netty4】深入学习Netty

Netty is an asynchronous event-driven network application framework 
for rapid development of maintainable high performance protocol servers & clients

 

学习前,建议了解下java NIO相关知识,有助于对Netty中对象的理解。

NIO介绍,博客地址:https://blog.csdn.net/the_fool_/article/details/83000648

AIO、BIO、NIO的区别,博客地址:https://blog.csdn.net/anxpp/article/details/51512200

Netty如何封装Java NIO,博客地址::https://blog.csdn.net/tjreal/article/details/79751342

应用场景https://blog.csdn.net/LIAN_XL/article/details/79799072

官网:https://netty.io/

版本:目前最新版本为4.1.30

环境:JDK 5 (Netty 3.x) or 6 (Netty 4.x) is enough

八卦:Netty5被干掉的原因?极大增加了复杂度,效率却没有提升,作者干掉了master分支。

模块,结构:

支持的链接类型:普通链接、长连接、心跳检测等。

使用:官方的简单demo,用于介绍Netty 创建过程:

完整代码:https://blog.csdn.net/the_fool_/article/details/80611148

1、根据实际业务创建handle处理类,处理客户端请求实际信息:

package com.xxx.ann.netty.mostsimple;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil;

/**
 * Handles a server-side channel.
 * 实际上自定义的业务流程使用的是本类
 */
public class DiscardServerHandler extends ChannelInboundHandlerAdapter { // (1)
    /**
     * Server读取信息的方法
     * @param ctx
     * @param msg
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        ByteBuf in = (ByteBuf) msg;
        try {
            while (in.isReadable()) { // (1)
                System.out.print((char) in.readByte());
                System.out.flush();
            }
            // 向客户端发送消息
            String response = "hello client!";
            // 在当前场景下,发送的数据必须转换成ByteBuf数组
            ByteBuf encoded = ctx.alloc().buffer(4 * response.length());
            encoded.writeBytes(response.getBytes());
            ctx.write(encoded);
            ctx.flush();
        } finally {
            ReferenceCountUtil.release(msg); // (2)
        }
    }

    /**
     * 处理异常
     * @param ctx
     * @param cause
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // (4)
        // Close the connection when an exception is raised.
        cause.printStackTrace();
        ctx.close();
    }
}

2、Server 端代码:

package com.xxx.ann.netty.mostsimple;

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;

/**
 * server 端
 */
public class DiscardServer {
    private int port;
    public DiscardServer(int port){
        this.port=port;
    }

    public void run() throws Exception{
        /**EventLoopGroup:IO操作的多线程组
         *boss:
         * accepts an incoming connection 处理链接
         *worker:
         * handles the traffic of the accepted connection once
         * the boss accepts the connection and registers the accepted
         * connection to the worker 处理实际逻辑
         * 使用多少线程以及如何将它们映射到创建的通道取决于EventLoopGroup实现,甚至可以通过构造函数进行配置。
         * */
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
        /**ServerBootstrap是一个建立服务器的助手类。可以直接使用通道设置服务器。
        */
            ServerBootstrap b = new ServerBootstrap();

            b.group(bossGroup, workerGroup)
            /**Here, we specify to use the NioServerSocketChannel class which is used to
             * instantiate a new Channel to accept incoming connections.*/
                    .channel(NioServerSocketChannel.class)
                    /***
                     * 这里指定处理程序将始终由新接受的通道进行处理
                     * ChannelInitializer:是专门帮助用户配置新通道的特殊处理程序。
                     * 实际使用需要抽取到顶级类并自定义业务逻辑代码
                     */
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) throws Exception {
                            ch.pipeline().addLast(new DiscardServerHandler());
                        }
                    })
                    /**特定通道实现参数,具体含义:https://netty.io/4.1/api/io/netty/channel/ChannelOption.html
                     *option() is for the NioServerSocketChannel that accepts incoming connections
                     * childOption() is for the Channels accepted by the parent ServerChannel
                     * */
                    .option(ChannelOption.SO_BACKLOG, 128)

                    .childOption(ChannelOption.SO_KEEPALIVE, true);
            /** Bind and start to accept incoming connections.*/
            ChannelFuture f = b.bind(port).sync();

            /**
             * Wait until the server socket is closed.
             * In this example, this does not happen, but you can do that to gracefully
             * shut down your server.
             * */
            f.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) throws Exception {
        int port=8081;
        new DiscardServer(port).run();
    }
}

3、浏览器进入licalhost:8081或者telnet localhost 8081可访问服务端,可在控制台查看到已经建立连接并访问成功(本demo不会成功返回数据)。

 

 

更多参考资料:https://mp.weixin.qq.com/s/IyWWeI7oWjvMgIWwizbLqA

posted @ 2018-10-11 17:09  黑猫先生  阅读(486)  评论(0编辑  收藏  举报