Netty初识-主要类的总览

关键词:Netty    NIO

学习Netty前,建议先学习Java BIO、NIO、Selector等基础知识,请戳《网络编程从BIO到NIO》《网络编程IO多路复用

Netty在JDK NIO源码的基础上进行扩展。包括对JDK中的Channel、SocketChannel、ServerSocketChannel、ByteBuffer等都进行的重新编写。本文先对Netty中的主要类有个初步的认识。


相关类

  • Channel

io.netty.channel.Channel。可以将其看似JDK中的java.nio.channels.Channel。其表示一个网络Socket连接,并且具有read、write、connect、bind等IO操作。

①Channel父类继承图

②Channel子类实现图

  • EventLoop

处理IO操作的事件循环器。监听是否有accept、read、write等操作。

  • EventLoopGroup

一个多线程的处理IO操作的事件循环组,每一个单线程便是一个EventLoop事件循环器。EventLoopGroup继承了JDK提供的ScheduleExecutorService,具有异步定时执行功能。(如果你有Java Selector的使用经验,可以看出这里定时执行的是select方法,究竟是不是这样?后续深入源码看看)。一个EcentLoopGroup可以对应多个EventLoop,即对应多个Selector。

  • ServerBootstrap、Bootstrap

ServerBootstrap是方便快速创建服务端服务的引导类,服务端代码编程从构建ServerBootstrap开始。使用其中的方法完成端口的绑定、相关连接参数的设置、相关事件处理器的设置等。

Bootstrap是快速创建客户端服务的引导类,客户端编程从构建Bootstrap开始。

  • ByteBuf

用于Channel读写数据的缓冲区,相当于JDK中的java.nio.ByteBuffer

  • ChannelConfig、ChannelOption

设置Channel的相关配置,比如Socket连接超时时长等。ChannelOption类提供了预设的相关配置信息。

  • ChannelFuture

Netty中所有的IO操作都是异步的,即调用IO操作方法时,方法会立即返回一个ChannelFuture对象,即使IO数据没有准备好。

  • ChannelHandler

负责处理IO事件。比如接收客户端数据(read)、给客户端响应数据(write)等。可以将其看做Java Servlet中的Filter过滤器机制。

ChannelInboundHandler

从读取数据方向开始,依次执行ChannelInboundHandler。即调用了SocketChannel的read方法之后,便会依次执行ChannelInboundHandler(按照ChannelPipeline中顺序)。

方便理解的记忆方式是此Handelr处理客户端的request,处理方向从客户端方向流向服务端方向。

抽象类ChannelInboundHandlerAdapter实现ChannelInboundHandler接口,提供基础的实现方法。

ChannelOutboundHandler

与ChannelInboundHandler相反,朝着写数据的方向依次执行。即在调用SocketChannel的write方法之前,依次执行ChannelOutboundHandler。

方便理解的记忆方式是此Handelr处理响应客户端的response,处理方向从服务端方向流向客户端方向。

抽象类ChannelOutboundHandlerAdapter实现ChannelOutboundHandler接口,提供基础的实现方法。

  • ChannelPipeline

ChannelHandler组成的链表就成了ChannelPipeline。request和response按照ChannelPipeline中的ChannelHandler顺序执行逻辑。可以将其看做Java Servlet中的FilterChain机制。

ChannelPipeline与ChannelHandler示意图:

从Socket.read()方法开始之后的ChannelInboundHandler 1按照箭头方向依次到ChannelOutboundHandler N,便组成了ChannelPipeline。(是不是和Filter的方式类似啊?)

  • ChannelHandlerContext

在ChannelPipeline与ChannelHandler中传输数据的上下文。Netty将请求和响应的相关信息封装成ChannelHandlerContext对象。就像Filter中传输的对象是ServerletRequestServletResponse

简单地使用Netty搭建服务端例子:

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

import java.net.SocketAddress;

/**
 * 使用Netty搭建服务端
 */
public class MyServer {

    public static void main(String[] args) {
        // 创建两个线程组,bossGroup负责accept客户端的连接
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        // workerGroup负责处理bossGroup已经accept的Socket的操作,如read、write等。
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            // 创建Serverbootstrap
            ServerBootstrap b = new ServerBootstrap();
            // 设置boss和worker线程组
            b.group(bossGroup, workerGroup)
                    // 设置使用NioServerSocketChannel类型封装所accept的SocketChannel对象
                    .channel(NioServerSocketChannel.class)
                    // 设置SocketChannel的处理器,处理SocketChannel的相关操作
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) throws Exception {
                            ch.pipeline().addLast(new MyServerHandler());
                        }
                    })
                    // 设置服务端最大支持同时连接128个客户端
                    .option(ChannelOption.SO_BACKLOG, 128)
                    // 设置与客户端的Socket保持连接
                    .childOption(ChannelOption.SO_KEEPALIVE, true);

            // 绑定端口号,开始监听客户端的连接
            ChannelFuture f = b.bind(8800).sync();

            // 阻塞等待,直到服务端Server Socket关闭
            f.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }

    /**
     * 自定义ChannelHandler,处理IO操作
     *
     */
    public static class MyServerHandler extends ChannelInboundHandlerAdapter {
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            Channel channel = ctx.channel();
            SocketAddress socketAddress = channel.remoteAddress();
            System.out.println("客户端【"+socketAddress+"】发来数据:" + new String(((ByteBuf)msg).array()));
        }
    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值