一节课让你学透Netty编程

开课吧开课吧锤锤2021-04-28 17:33

点赞
有用
分享分享

    Netty是一个异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能服务器和客户端。它是一个NIO客户机服务器框架,支持快速、简单地开发网络应用程序,如服务器和客户机。Netty大大简化了网络编程,如TCP和UDP套接字服务器。

    但很多学员都向小开反应,一直在学Netty,但不得其法,学习的进度很慢。4月27日的《HelloWorld公开课》就是为了解决你的这个问题,跟着宏彪老师,一节课让你搞懂Netty。

    Netty核心概念

    在正式开始Netty学习前,我们先来了解几个Netty框架中的核心概念,Channel(管道),其是对Socket的封装,其包含了一组API,大大简化了直接与Socket进行操作的复杂性。

    EventLoopGroup是一个EventLoop池,包含很多的EventLoop。Netty为每个Channel分配了一个EventLoop,用于处理用户连接请求、对用户请求的处理等所有事件。EventLoop本身只是一个线程驱动在其生命周期内只会绑定一个线程,让该线程处理一个Channel的所有IO事件。

    ServerBootstrap用于配置整个Netty代码,将各个组件关联起来。服务端使用的是ServerBootstrap,而客户端使用的是则Bootstrap。

    ChannelHandler是对Channel中数据的处理器,这些处理器可以是系统本身定义好的编

    解码器,也可以是用户自定义的。这些处理器会被统一添加到一个ChannelPipeline的对象中,然后按照添加的顺序对Channel中的数据进行依次处理。

    Netty中所有的I/O操作都是异步的,即操作不会立即得到返回结果,所以Netty中定义了一个ChannelFuture对象作为这个异步操作的“代言人”,表示异步操作本身。

    如果想获取到该异步操作的返回值,可以通过该异步操作对象的addListener()方法为该异步操作添加监听器,为其注册回调:当结果出来后马上调用执行。Netty的异步编程模型都是建立在Future与回调概念之上的。

Java

    Scoket编程

    定义服务端启动类

public class SomeServer {
    public static void main(String[] args) {
        // 创建一个group,用于处理客户端连接请求
        NioEventLoopGroup parentGroup = new NioEventLoopGroup();
        // 创建一个group,用于处理客户端连接上server后的后续请求
        NioEventLoopGroup childGroup = new NioEventLoopGroup();

        try {
            // bootstrap用于初始化channel
            ServerBootstrap bootstrap = new ServerBootstrap();
            // 指定要使用的两个group
            bootstrap.group(parentGroup, childGroup)
            // 指定要创建的channel的类型
            .channel(NioServerSocketChannel.class)
            // 指定要使用的处理器
            .childHandler(new ChannelInitializer<SocketChannel>() {

             // 初始化channel的方法
             @Override
             protected void initChannel(SocketChannel ch)
             throws Exception {
             // channel一旦创建完毕,其就会同时绑定一个pipeline
             ChannelPipeline pipeline = ch.pipeline();
             // 添加编码器
             pipeline.addLast(new StringEncoder());
             // 添加解码器
             pipeline.addLast(new StringDecoder());
             // 添加自定义的处理器
             pipeline.addLast(new SomeServerHandler());
                        }
                    });

            // 创建channel,绑定到指定的主机(hostName,port)
            // sync()是将异步变同步
            ChannelFuture future = bootstrap.bind(8888).sync();
            System.out.println("服务器8888已经启动。。。");
            // 当channel被关闭后,会触发closeFuture()的执行,去完成一些收尾工
             作
            future.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            // 将两个group进行优雅关闭
            parentGroup.shutdownGracefully();
            childGroup.shutdownGracefully();
        }
    }
}

    定义服务端处理器

// 自定义服务端处理器,用于处理来自于客户端的数据
public class SomeServerHandler extends ChannelInboundHandlerAdapter {

    // 一种回调方法:当client将数据写入到channel并发送到server后,server端就会触发该方法的执行

    /**
     *
     * @param ctx 其代表当前处理器(其实它是当前处理器所封装的一个节点)
     * @param msg 就是client端发送来的数据
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) 
    throws Exception {
        // 输出client的地址与发送来的数据
        System.out.println(ctx.channel().remoteAddress() + ", " + msg);
        // 向client发送一个随机的UUID
        ctx.channel().writeAndFlush("from server: " + UUID.randomUUID());
        TimeUnit.MILLISECONDS.sleep(500);
    }

    // 一旦在服务端发生异常,就会触发该方法的执行
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable 
    cause) throws Exception {
        cause.printStackTrace();
        // 关闭channel
        ctx.close();
    }
}

    同理,我们也可以定义客户端的启动类和处理器,这里因为篇幅问题我们就不贴具体代码了,感兴趣的同学可以点击手把手带你写第一个Netty观看公开课的视频回放呦

    Netty实现HTTP请求处理

    首先定义服务器启动类,该服务器用于创建并初始化服务器启动对象ServerBootStrap。

public class HttpServer {
    public static void main(String[] args)
                               throws InterruptedException {
        EventLoopGroup parentGroup = new NioEventLoopGroup();
        EventLoopGroup childGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap bootstrap = new ServerBootstrap();

            bootstrap.group(parentGroup, childGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new HttpChannelInitializer());

            ChannelFuture future = bootstrap.bind(8888).sync();
            System.out.println("服务器启动了,端口号8888");
            future.channel().closeFuture().sync();

        } finally {
            parentGroup.shutdownGracefully();
            childGroup.shutdownGracefully();
        }
    }
}

    定义管道初始化器

public class HttpChannelInitializer
    extends ChannelInitializer<SocketChannel> {
    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();
        pipeline.addLast(new HttpServerCodec());
        pipeline.addLast(new HttpServerHandler());
    }
}

    接下来,我们再定义服务端处理器就好了,剩下的代码我们就不写了,如果有同学想要到了解整个项目的源代码,可以点击下方图片

   Java

    讲师介绍

    宏彪老师,原百度好看架构师,现沪智科技技术合伙人

    《Hello,World公开课》是由开课吧推出的面向广大开发工程师的免费加餐课,集结业内名师大咖,聚焦热门技术和实战解决方案,以专业知识分享交流为桥梁,链接正在创造世界的一群科技主力们,向初心致敬,为技术发烧。无论你是初入职场的应届生,还是准备升职加薪的职场精英,相信这里都有你需要的养料。

    以上就是开课吧广场小编为大家整理发布的“一节课让你学透Netty编程”一文,更多动态相关内容尽在开课吧广场开课吧动态频道!

有用
分享