Netty8-Netty核心模块2

314 阅读3分钟

我正在参加「掘金·启航计划」

ChannelHandlerContext

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

• ChannelFuture close(),关闭通道
• ChannelOutboundInvoker flush(),刷新
• ChannelFuture writeAndFlush(Object msg) , 将 数 据 写 到 ChannelPipeline 中 当 前
• ChannelHandler 的下一个 ChannelHandler 开始处理(出站)

ChannelOption

  1. Netty 在创建 Channel 实例后,一般都需要设置 ChannelOption 参数。
  2. ChannelOption 参数如下:
    ChannelOption.SO_BACKLOG
    对应 TCP/IP 协议 listen 函数中的 backlog 参数,用来初始化服务器可连接队列大小。服
    务端处理客户端连接请求是顺序处理的,所以同一时间只能处理一个客户端连接。多个客户
    端来的时候,服务端将不能处理的客户端连接请求放在队列中等待处理,backlog 参数指定
    了队列的大小。
    ChannelOption.SO_KEEPALIVE
    一直保持连接活动状态

EventLoopGroup 和其实现类 NioEventLoopGroup

  1. EventLoopGroup 是一组 EventLoop 的抽象,Netty 为了更好的利用多核 CPU 资源,一般会有多个 EventLoop 同时工作,每个 EventLoop 维护着一个 Selector 实例。
  2. EventLoopGroup 提供 next 接口,可以从组里面按照一定规则获取其中一个EventLoop来处理任务。在 Netty 服务器端编程中,我们一般都需要提供两个EventLoopGroup,例如:BossEventLoopGroup 和 WorkerEventLoopGroup。
    BossEventLoopGroup 通常是一个单线程的 EventLoop,EventLoop 维护着一个注册了ServerSocketChannel 的
    Selector 实例BossEventLoop 不断轮询Selector 将连接事件分离出来

    通常是 OP_ACCEPT 事件,然后将接收到的 SocketChannel 交给WorkerEventLoopGroup
    WorkerEventLoopGroup 会由 next 选择其中一个 EventLoop来将这个SocketChannel 注册到其维护的Selector 并对其后续的 IO 事件进行处理
    在这里插入图片描述
  3. 常用方法
public NioEventLoopGroup(),构造方法
• public Future<?> shutdownGracefully(),断开连接,关闭线程

Unpooled 类

  1. Netty 提供一个专门用来操作缓冲区(即Netty的数据容器)的工具类
  2. 常用方法如下所示
//通过给定的数据和字符编码返回一个 ByteBuf 对象(类似于 NIO 中的 ByteBuffer 但有区别)
public static ByteBuf copiedBuffer(CharSequence string, Charset charset)
  1. 举例说明Unpooled 获取 Netty的数据容器ByteBuf 的基本使用
    在这里插入图片描述
package com.atguigu.netty.buf;

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

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


        //创建一个ByteBuf
        //说明
        //1. 创建对象,该对象包含一个数组arr , 是一个byte[10]
        //2. 在netty 的buffer中,不需要使用flip 进行反转
        //   底层维护了 readerindex 和 writerIndex 所以不用反转
        //3. 通过 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=" + buffer.capacity());//10
        //输出
//        for(int i = 0; i<buffer.capacity(); i++) {
//            System.out.println(buffer.getByte(i));
//        }
        //capacity返回buf数组对应的长度
        for(int i = 0; i < buffer.capacity(); i++) {
            System.out.println(buffer.readByte());
        }
        System.out.println("执行完毕");
    }
}
package com.atguigu.netty.buf;

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

import java.nio.charset.Charset;

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

        //创建ByteBuf
        ByteBuf byteBuf = Unpooled.copiedBuffer("hello,world!", Charset.forName("utf-8"));

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

            byte[] content = byteBuf.array();

            //将 content 转成字符串
            System.out.println(new String(content, Charset.forName("utf-8")));

            System.out.println("byteBuf=" + byteBuf);

            System.out.println(byteBuf.arrayOffset()); // 0
            System.out.println(byteBuf.readerIndex()); // 0
            System.out.println(byteBuf.writerIndex()); // 12
            System.out.println(byteBuf.capacity()); // 36

            //System.out.println(byteBuf.readByte()); //
            System.out.println(byteBuf.getByte(0)); // 104

            int len = byteBuf.readableBytes(); //可读的字节数  12
            System.out.println("len=" + len);

            //使用for取出各个字节
            for(int i = 0; i < len; i++) {
                System.out.println((char) byteBuf.getByte(i));
            }

            //按照某个范围读取
            System.out.println(byteBuf.getCharSequence(0, 4, Charset.forName("utf-8"))); //hell
            System.out.println(byteBuf.getCharSequence(4, 6, Charset.forName("utf-8"))); //o,worl


        }


    }
}