0
点赞
收藏
分享

微信扫一扫

13-Netty 核心模块组件


Bootstrap, ServerBootstrap


  1. Bootstrap 意思是引导, 一个Netty应用通常由一个Bootstrap开始, 主要作用的配置整个Netty程序, 串联各个组件, Netty中Bootstrap类是客户端程序的启动引导类, ServerBootstrap是服务器端程序的启动引导类
  2. 常见的方法有:


  1. public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup), 用于设置服务端的BossGroup和WorkerGroup
  2. public B group(EventLoopGroup group), 用于设置客户单的EventLoopGroup


public B channel(Class<? extends C> channelClass), 该方法用来设置一个服务器端的通道实现public <T> B option(ChannelOption<T> option, T value), 该方法用来ServerChannel添加配置


public <T> ServerBootstrap childOption(ChannelOption<T> childOption, T value), 用来给接收到的通道添加配置public ServerBootstrap childHandler(ChannelHandler childHandler), 该方法用来设置业务处理类(自定义的Handler)


public ChannelFuture bind(int inetPort), 该方法用于服务端,用来设置绑定的端口public ChannelFuture connect(InetAddress inetHost, int inetPort), 该方法用于客户端, 用来连接服务器端

Future, ChannelFuture

Netty中所有的IO操作都是异步的, 不能立刻得知消息是否被正确处理, 但是可以过一会等它执行完成或者直接注册一个监听器, 具体的实现就是通过Future和ChannelFuture, 他们可以注册一个监听, 当操作执行成功或者失败时监听会自动触发注册的监听事件

常见方法:


  • Channel channel() , 返回当前正在进行 IO 的通道
  • ChannelFuture sync() , 等待异步操作执行完成

Channel


  1. Netty网络通信的组件,能够用于执行网络IO操作
  2. 通过channel可获得当前网络连接的通道的状态


  3. 通过channel可获得网络连接的配置参数(例如接收缓冲区大小)
  4. channel提供异步的网络IO操作(如建立连接, 读写,绑定端口), 异步调用意味着任何IO调用都将立即返回,并且不保证在调用结束时所请求的IO操作已完成


  5. 调用立即返回一个ChannelFuture实例, 通过注册监听器到ChannelFuture上, 可以IO操作成功, 失败或取消时回调通知方
  6. 支持关联IO操作与对应的处理程序


  7. 不同协议, 不同的阻塞类型的连接都有不同的Channel类型与之对应,常用的Channel类型:


  1. NioSocketChannel, 异步的客户端 TCP socket连接
  2. NioServerSocketChannel, 异步的服务器端TCP socket连接


  3. NioDatagramChannel, 异步的UDP连接
  4. NioSctpChannel, 异步的客户端Sctp连接


  5. NioSctpServerChannel, 异步的Sctp服务器端连接
  6. 这些通道涵盖了UDP和TCP网络IO以及文件IO

Selector


  1. Netty基于Selector对象实现IO多路复用, 通过Selector一个线程可以监听多个连接的Channel事件
  2. 当一个Selector中注册Channel后, Selector内部的机制就可以自动不断的查询(Select)这些注册的Channel是否有已就绪的IO事件(例如可读, 可写, 网络连接完成等), 这样程序就可以很简单的使用一个线程高效的管理多个Channel

ChannelHandler 及其实现类


  1. ChannelHandler是一个接口, 处理IO事件或者拦截IO操作, 并将其转发到其ChannelPipeline(业务处理链)中的下一个处理程序
  2. ChannelHandler本身并没有提供很多方法, 因为这个接口有很多的方法需要去实现, 方便使用期间, 可以集成他的子类


  3. ChannelHandler及其实现类一览图(后)

13-Netty 核心模块组件_.net


  1. 我们经常需要自定义一个handler类去继承ChannelInboundHandlerAdapter, 然后重写相应的方法实现业务逻辑, 我们接下来看看一般都需要重写那些方法

13-Netty 核心模块组件_io操作_02

Pipeline 和 ChannelPipeline

ChannelPipeline是一个重点:


  1. ChannelPipeline是一个Handler的集合, 它负责处理和拦截inbound和outbound的事件和操作, 相当于一个贯穿Netty 的链. (也可以这样理解, ChannelPipeline是保存ChannelHandler的List, 用于处理或拦截Channel的入站事件和出站操作)
  2. ChannelPipeline实现了一种高效形式的拦截过滤器模式, 使用户可以完全控制事件的处理方式, 以及Channel 中各个的ChannelHandler如何交互


  3. 在Netty中每个Channel都有且仅有一个ChannelPipeline与之对应, 他们的组成关系如下

13-Netty 核心模块组件_.net_03

13-Netty 核心模块组件_bootstrap_04


  1. 常用方法


  1. ChannelPipeline addFirst(ChannelHandler... handlers), 把一个业务处理类(Handler), 添加到链中的第一个位置
  2. ChannelPipeline addLast(ChannelHandler... handlers), 把一个业务处理类(Handler), 添加到链中的最后一个位置

入站 出站

13-Netty 核心模块组件_bootstrap_05


ChannelHandlerContext


  1. 保存Channel相关信息的上下文对象, 同时关联一个CHannel对象
  2. 即ChannelHandlerContext中包含一个具体的事件处理器ChannelHandler, 同时ChannelHandlerContext 中也绑定了对应的pipeline和Channel信息,方便对ChannelHandler进行调用


  3. 常用方法:

13-Netty 核心模块组件_bootstrap_06

ChannelOption


  1. Netty在创建Channel实例后, 一般都需要设置ChannelOption参数
  2. ChannelOption参数如下:

13-Netty 核心模块组件_bootstrap_07

EventLoopGroup和其实现类NioEventLoopGroup


  1. EventLoopGroup是一组EventLoop的抽象,Netty 为了更好的利用多核CPU资源, 一般会有多个EventLoop同时工作, 每个EventLoop维护者一个Selector实例
  2. EventLoopGroup提供next接口, 可以从组里面按照一定规则获取其中一个EventLoop来处理任务, 在Netty服务器端编程中, 我们一般都需要提供两个EventLoopGroup 例如:BossEventLoopGroup 和 WorkerEventLoopGroup


  3. 通常一个服务器端口即一个ServerSocketChannel 对应一个 Selector 和一个EventLoop线程, BOSSEventLoop负责接收客户端的连接并将SocketChannel交给WorkerEventLoopGroup来进行IO处理,如下图所示

13-Netty 核心模块组件_io操作_08


  1. 常用方法


  1. public NioEventLoopGroup() 构造方法
  2. public Future<?> shutdownGracefully(), 断开连接关闭线程

Unpooled类


  1. Netty提供了一个专门用来操作缓冲区(即 Netty的数据容器)的工具类
  2. 常用方法如下

13-Netty 核心模块组件_.net_09


  1. 举例说明Unpooled获取Netty的数据容器ByteBuf的基本使用[案例演示]

13-Netty 核心模块组件_.net_10

案例一

package com.dance.netty.netty.buf;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;

public class NettyByteBuf01 {

public static void main(String[] args) {

/*
* 创建一个ByteBuf
* 创建对象, 该对象包含一个数组arr, 是一个byte[10]
* 在Netty的Buffer中, 不需要使用flip进行反转
* 底层维护了readerIndex 和 writerIndex
* 通过readerIndex, writerIndex, capacity 将buffer分为三个区域
* 0 -> readerIndex : 已读区域
* readerIndex -> writerIndex : 未读区域
* writerIndex -> capacity : 可写区域
*/
ByteBuf buffer = Unpooled.buffer(10);

for (int i = 0; i < 10; i++) {
buffer.writeByte(i);
}

System.out.println("capacity is "+buffer.capacity());

// readByte会使 readerIndex增长 如果指定位置则不会
for (int i = 0; i < buffer.capacity(); i++) {
System.out.println(buffer.readByte());
}

}

}


案例二

package com.dance.netty.netty.buf;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;

import java.nio.charset.StandardCharsets;

public class NettyByteBuf02 {
public static void main(String[] args) {

ByteBuf byteBuf = Unpooled.copiedBuffer("hello,world!", StandardCharsets.UTF_8);

// 调用相关的方法
if(byteBuf.hasArray()){

// 获取字节数组
byte[] array = byteBuf.array();

// 转为字符串输出
System.out.println(new String(array,StandardCharsets.UTF_8));

// 输出ByteBuf
System.out.println("byte buf is " + byteBuf);

// 数组偏移量
System.out.println(byteBuf.arrayOffset());

// readerIndex 位置
System.out.println(byteBuf.readerIndex());

// writerIndex 位置
System.out.println(byteBuf.writerIndex());

// capacity 边界
System.out.println(byteBuf.capacity());

// 读取宇哥字节
System.out.println(byteBuf.readByte());

// 读取指定位置的一个字节
System.out.println(byteBuf.getByte(0));

// 可读的字节数
System.out.println(byteBuf.readableBytes());

for (int i = 0; i < byteBuf.readableBytes(); i++) {
System.out.println((char)byteBuf.getByte(i));
}

// 从0开始读取4个字节
System.out.println(byteBuf.getCharSequence(0, 4, StandardCharsets.UTF_8));
// 从4开始读取6个字节
System.out.println(byteBuf.getCharSequence(4, 6, StandardCharsets.UTF_8));

}
}
}


举报

相关推荐

0 条评论