Netty教程 / 第 30 节

第3章:Netty 核心组件

本章导读

Netty 的强大之处在于其优雅的组件设计。本章将深入讲解 Netty 的五大核心组件:Channel、EventLoop、ChannelFuture、ChannelHandler 和 ChannelPipeline,理解这些组件是掌握 Netty 的关键。


3.1 Channel(通道)

3.1.1 Channel 概述

定义:Channel 是 Netty 网络操作的抽象类,代表一个网络连接。

核心特性

  • 双向通信(可读可写)
  • 异步操作
  • 支持多种传输类型(NIO、OIO、Local、Embedded)

3.1.2 Channel 的层次结构

Channel (接口)
    ├── AbstractChannel (抽象类)
    │   ├── AbstractNioChannel
    │   │   ├── NioServerSocketChannel    # 服务端Channel
    │   │   └── NioSocketChannel           # 客户端Channel
    │   ├── AbstractOioChannel
    │   │   ├── OioServerSocketChannel
    │   │   └── OioSocketChannel
    │   └── LocalChannel                   # 本地通信
    └── EmbeddedChannel                    # 测试用

3.1.3 常用 Channel 类型

Channel 类型说明使用场景
NioServerSocketChannelNIO 服务端TCP 服务器
NioSocketChannelNIO 客户端TCP 客户端
NioDatagramChannelNIO UDPUDP 通信
OioServerSocketChannelBIO 服务端阻塞 I/O(不推荐)
LocalChannel本地通信JVM 内部通信
EmbeddedChannel嵌入式单元测试

3.1.4 Channel 的核心方法

public interface Channel extends AttributeMap, ChannelOutboundInvoker, Comparable<Channel> {
    
    // 获取Channel的唯一标识
    ChannelId id();
    
    // 获取EventLoop
    EventLoop eventLoop();
    
    // 获取父Channel(服务端Channel)
    Channel parent();
    
    // 获取配置
    ChannelConfig config();
    
    // Channel是否打开
    boolean isOpen();
    
    // Channel是否注册到EventLoop
    boolean isRegistered();
    
    // Channel是否激活(连接建立)
    boolean isActive();
    
    // 获取本地地址
    SocketAddress localAddress();
    
    // 获取远程地址
    SocketAddress remoteAddress();
    
    // 获取Pipeline
    ChannelPipeline pipeline();
    
    // 读取数据
    Channel read();
    
    // 写入数据(不刷新)
    ChannelFuture write(Object msg);
    
    // 刷新数据到网络
    Channel flush();
    
    // 写入并刷新
    ChannelFuture writeAndFlush(Object msg);
    
    // 关闭Channel
    ChannelFuture close();
}

3.1.5 Channel 的生命周期

channelUnregistered  →  channelRegistered  →  channelActive  →  channelInactive
        ↑                                                              ↓
        └──────────────────────────────────────────────────────────────┘

状态说明

状态说明
ChannelUnregisteredChannel 已创建,但未注册到 EventLoop
ChannelRegisteredChannel 已注册到 EventLoop
ChannelActiveChannel 已激活,可以收发数据
ChannelInactiveChannel 未连接到远程节点

3.1.6 Channel 示例代码

public class ChannelDemo {
    public static void main(String[] args) throws Exception {
        EventLoopGroup group = new NioEventLoopGroup();
        
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(group)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) {
                            ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {
                                @Override
                                public void channelActive(ChannelHandlerContext ctx) {
                                    Channel channel = ctx.channel();
                                    
                                    // 打印Channel信息
                                    System.out.println("Channel ID: " + channel.id());
                                    System.out.println("本地地址: " + channel.localAddress());
                                    System.out.println("远程地址: " + channel.remoteAddress());
                                    System.out.println("是否激活: " + channel.isActive());
                                    System.out.println("是否打开: " + channel.isOpen());
                                    System.out.println("是否可写: " + channel.isWritable());
                                    
                                    // 发送数据
                                    ByteBuf buf = Unpooled.copiedBuffer("Hello Server", CharsetUtil.UTF_8);
                                    channel.writeAndFlush(buf);
                                }
                            });
                        }
                    });
            
            ChannelFuture future = bootstrap.connect("localhost", 8080).sync();
            future.channel().closeFuture().sync();
        } finally {
            group.shutdownGracefully();
        }
    }
}

3.2 EventLoop(事件循环)

3.2.1 EventLoop 概述

定义:EventLoop 是 Netty 的核心抽象,负责处理 I/O 事件和任务调度。

核心概念

  • 一个 EventLoop 绑定一个线程
  • 一个 EventLoop 可以处理多个 Channel
  • 一个 Channel 只能注册到一个 EventLoop

3.2.2 EventLoop 的层次结构

EventExecutorGroup
    ├── EventLoopGroup
    │   ├── MultithreadEventLoopGroup
    │   │   ├── NioEventLoopGroup        # NIO事件循环组
    │   │   ├── EpollEventLoopGroup      # Linux epoll
    │   │   └── KQueueEventLoopGroup     # macOS kqueue
    │   └── DefaultEventLoopGroup
    └── EventExecutor
        └── EventLoop
            ├── NioEventLoop
            ├── EpollEventLoop
            └── KQueueEventLoop

3.2.3 EventLoop 与 Channel 的关系

EventLoopGroup (线程组)
    ├── EventLoop (线程1)
    │   ├── Channel A
    │   ├── Channel B
    │   └── Channel C
    ├── EventLoop (线程2)
    │   ├── Channel D
    │   └── Channel E
    └── EventLoop (线程3)
        └── Channel F

关键点

  • ✅ 一个 Channel 的所有 I/O 操作都在同一个 EventLoop 中执行
  • ✅ 避免了多线程竞争,无需加锁
  • ✅ 保证了事件的顺序性

3.2.4 EventLoop 的核心方法

public interface EventLoop extends OrderedEventExecutor, EventLoopGroup {
    
    // 获取父EventLoopGroup
    @Override
    EventLoopGroup parent();
    
    // 注册Channel
    ChannelFuture register(Channel channel);
    
    // 判断当前线程是否是EventLoop线程
    boolean inEventLoop();
    
    // 提交任务
    Future<?> submit(Runnable task);
    
    // 调度任务
    ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit);
    
    // 周期性调度
    ScheduledFuture<?> scheduleAtFixedRate(Runnable command, 
                                           long initialDelay, 
                                           long period, 
                                           TimeUnit unit);
}

3.2.5 EventLoopGroup 的创建

// 1. 默认线程数(CPU核心数 * 2)
EventLoopGroup group = new NioEventLoopGroup();

// 2. 指定线程数
EventLoopGroup group = new NioEventLoopGroup(4);

// 3. 指定线程工厂
EventLoopGroup group = new NioEventLoopGroup(4, new ThreadFactory() {
    private AtomicInteger index = new AtomicInteger(0);
    
    @Override
    public Thread newThread(Runnable r) {
        return new Thread(r, "MyEventLoop-" + index.getAndIncrement());
    }
});

// 4. Boss和Worker分离
EventLoopGroup bossGroup = new NioEventLoopGroup(1);      // 接收连接
EventLoopGroup workerGroup = new NioEventLoopGroup();     // 处理I/O

3.2.6 EventLoop 任务调度示例

public class EventLoopTaskDemo {
    public static void main(String[] args) {
        EventLoopGroup group = new NioEventLoopGroup();
        
        // 获取一个EventLoop
        EventLoop eventLoop = group.next();
        
        // 1. 提交普通任务
        eventLoop.execute(() -> {
            System.out.println("执行普通任务: " + Thread.currentThread().getName());
        });
        
        // 2. 提交延迟任务(3秒后执行)
        eventLoop.schedule(() -> {
            System.out.println("执行延迟任务: " + Thread.currentThread().getName());
        }, 3, TimeUnit.SECONDS);
        
        // 3. 提交周期性任务(每2秒执行一次)
        eventLoop.scheduleAtFixedRate(() -> {
            System.out.println("执行周期任务: " + Thread.currentThread().getName());
        }, 1, 2, TimeUnit.SECONDS);
        
        // 等待10秒后关闭
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        group.shutdownGracefully();
    }
}

3.3 ChannelFuture(异步结果)

3.3.1 ChannelFuture 概述

定义:ChannelFuture 是 Netty 异步操作的结果占位符。

为什么需要 ChannelFuture?

  • Netty 的所有 I/O 操作都是异步的
  • 操作会立即返回,但结果可能还未完成
  • ChannelFuture 用于获取操作结果或添加监听器

3.3.2 ChannelFuture 的状态

                未完成 (Uncompleted)
                        ↓
        ┌───────────────┴───────────────┐
        ↓                               ↓
    成功 (Success)                  失败 (Failure)

状态判断

ChannelFuture future = channel.writeAndFlush(msg);

// 判断是否完成
boolean isDone = future.isDone();

// 判断是否成功
boolean isSuccess = future.isSuccess();

// 判断是否可取消
boolean isCancellable = future.isCancellable();

// 获取异常(如果失败)
Throwable cause = future.cause();

3.3.3 获取 ChannelFuture 结果的方式

方式1:阻塞等待(不推荐)

// 阻塞等待操作完成
ChannelFuture future = channel.writeAndFlush(msg);
future.sync();  // 或 future.await();

// 检查结果
if (future.isSuccess()) {
    System.out.println("发送成功");
} else {
    System.out.println("发送失败: " + future.cause());
}

方式2:添加监听器(推荐)

ChannelFuture future = channel.writeAndFlush(msg);

// 添加监听器
future.addListener(new ChannelFutureListener() {
    @Override
    public void operationComplete(ChannelFuture f) {
        if (f.isSuccess()) {
            System.out.println("发送成功");
        } else {
            System.out.println("发送失败: " + f.cause());
        }
    }
});

// 使用Lambda表达式(更简洁)
future.addListener((ChannelFutureListener) f -> {
    if (f.isSuccess()) {
        System.out.println("发送成功");
    } else {
        System.out.println("发送失败: " + f.cause());
    }
});

方式3:使用内置监听器

// 关闭连接
future.addListener(ChannelFutureListener.CLOSE);

// 关闭并打印异常
future.addListener(ChannelFutureListener.CLOSE_ON_FAILURE);

// 转发异常
future.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);

3.3.4 ChannelFuture 实战示例

public class ChannelFutureDemo {
    public static void main(String[] args) throws Exception {
        EventLoopGroup group = new NioEventLoopGroup();
        
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(group)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) {
                            ch.pipeline().addLast(new StringEncoder());
                        }
                    });
            
            // 1. 连接操作的Future
            ChannelFuture connectFuture = bootstrap.connect("localhost", 8080);
            
            // 添加连接监听器
            connectFuture.addListener((ChannelFutureListener) future -> {
                if (future.isSuccess()) {
                    System.out.println("连接成功");
                    Channel channel = future.channel();
                    
                    // 2. 写操作的Future
                    ChannelFuture writeFuture = channel.writeAndFlush("Hello Server");
                    
                    // 添加写监听器
                    writeFuture.addListener((ChannelFutureListener) f -> {
                        if (f.isSuccess()) {
                            System.out.println("数据发送成功");
                        } else {
                            System.out.println("数据发送失败: " + f.cause());
                        }
                    });
                } else {
                    System.out.println("连接失败: " + future.cause());
                }
            });
            
            // 3. 关闭操作的Future
            connectFuture.channel().closeFuture().addListener((ChannelFutureListener) future -> {
                System.out.println("连接已关闭");
            });
            
            // 等待连接关闭
            connectFuture.channel().closeFuture().sync();
        } finally {
            group.shutdownGracefully();
        }
    }
}

3.3.5 ChannelPromise

定义:ChannelPromise 是可写的 ChannelFuture,可以手动设置结果。

public class ChannelPromiseDemo {
    public static void main(String[] args) {
        EventLoopGroup group = new NioEventLoopGroup();
        EventLoop eventLoop = group.next();
        
        // 创建Promise
        ChannelPromise promise = new DefaultChannelPromise(channel, eventLoop);
        
        // 添加监听器
        promise.addListener((ChannelFutureListener) future -> {
            if (future.isSuccess()) {
                System.out.println("操作成功");
            } else {
                System.out.println("操作失败: " + future.cause());
            }
        });
        
        // 在另一个线程中设置结果
        new Thread(() -> {
            try {
                Thread.sleep(1000);
                // 设置成功
                promise.setSuccess();
                // 或设置失败
                // promise.setFailure(new Exception("操作失败"));
            } catch (InterruptedException e) {
                promise.setFailure(e);
            }
        }).start();
        
        group.shutdownGracefully();
    }
}

3.4 ChannelHandler(处理器)

3.4.1 ChannelHandler 概述

定义:ChannelHandler 是 Netty 的核心接口,用于处理 I/O 事件和业务逻辑。

分类

ChannelHandler
    ├── ChannelInboundHandler      # 入站处理器(处理读事件)
    └── ChannelOutboundHandler     # 出站处理器(处理写事件)

3.4.2 ChannelInboundHandler(入站处理器)

核心方法

public interface ChannelInboundHandler extends ChannelHandler {
    
    // Channel注册到EventLoop
    void channelRegistered(ChannelHandlerContext ctx);
    
    // Channel从EventLoop注销
    void channelUnregistered(ChannelHandlerContext ctx);
    
    // Channel激活(连接建立)
    void channelActive(ChannelHandlerContext ctx);
    
    // Channel失活(连接断开)
    void channelInactive(ChannelHandlerContext ctx);
    
    // 读取数据
    void channelRead(ChannelHandlerContext ctx, Object msg);
    
    // 读取完成
    void channelReadComplete(ChannelHandlerContext ctx);
    
    // 用户自定义事件
    void userEventTriggered(ChannelHandlerContext ctx, Object evt);
    
    // Channel可写状态改变
    void channelWritabilityChanged(ChannelHandlerContext ctx);
    
    // 异常捕获
    void exceptionCaught(ChannelHandlerContext ctx, Throwable cause);
}

常用实现类

类名说明
ChannelInboundHandlerAdapter适配器,提供默认实现
SimpleChannelInboundHandler泛型处理器,自动释放消息

示例

public class MyInboundHandler extends ChannelInboundHandlerAdapter {
    
    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        System.out.println("连接建立: " + ctx.channel().remoteAddress());
        ctx.fireChannelActive();  // 传递给下一个Handler
    }
    
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        System.out.println("接收到消息: " + msg);
        ctx.fireChannelRead(msg);  // 传递给下一个Handler
    }
    
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        System.err.println("发生异常: " + cause.getMessage());
        ctx.close();
    }
}

3.4.3 ChannelOutboundHandler(出站处理器)

核心方法

public interface ChannelOutboundHandler extends ChannelHandler {
    
    // 绑定地址
    void bind(ChannelHandlerContext ctx, SocketAddress localAddress, ChannelPromise promise);
    
    // 连接远程地址
    void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress, 
                 SocketAddress localAddress, ChannelPromise promise);
    
    // 断开连接
    void disconnect(ChannelHandlerContext ctx, ChannelPromise promise);
    
    // 关闭Channel
    void close(ChannelHandlerContext ctx, ChannelPromise promise);
    
    // 注销Channel
    void deregister(ChannelHandlerContext ctx, ChannelPromise promise);
    
    // 读取数据
    void read(ChannelHandlerContext ctx);
    
    // 写入数据
    void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise);
    
    // 刷新数据
    void flush(ChannelHandlerContext ctx);
}

常用实现类

类名说明
ChannelOutboundHandlerAdapter适配器,提供默认实现

示例

public class MyOutboundHandler extends ChannelOutboundHandlerAdapter {
    
    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
        System.out.println("发送消息: " + msg);
        ctx.write(msg, promise);  // 传递给下一个Handler
    }
    
    @Override
    public void flush(ChannelHandlerContext ctx) {
        System.out.println("刷新数据到网络");
        ctx.flush();
    }
}

3.4.4 SimpleChannelInboundHandler

优势:自动释放消息,避免内存泄漏

public class MySimpleHandler extends SimpleChannelInboundHandler<String> {
    
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) {
        // 处理消息
        System.out.println("接收到: " + msg);
        
        // 不需要手动释放msg,框架会自动释放
    }
    
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }
}

3.5 ChannelPipeline(处理链)

3.5.1 ChannelPipeline 概述

定义:ChannelPipeline 是 ChannelHandler 的容器,负责管理 Handler 的执行顺序。

核心特性

  • 双向链表结构
  • 入站事件从头到尾传播
  • 出站事件从尾到头传播

3.5.2 Pipeline 的结构

                    ChannelPipeline
┌───────────────────────────────────────────────────────────┐
│                                                           │
│  Head  →  Handler1  →  Handler2  →  Handler3  →  Tail   │
│   ↑                                                  ↓     │
│   └──────────────────────────────────────────────────┘     │
│                                                           │
└───────────────────────────────────────────────────────────┘

事件传播方向

  • 入站事件:Head → Handler1 → Handler2 → Handler3 → Tail
  • 出站事件:Tail → Handler3 → Handler2 → Handler1 → Head

3.5.3 Pipeline 的核心方法

public interface ChannelPipeline extends Iterable<Map.Entry<String, ChannelHandler>> {
    
    // 添加Handler(尾部)
    ChannelPipeline addLast(String name, ChannelHandler handler);
    ChannelPipeline addLast(ChannelHandler... handlers);
    
    // 添加Handler(头部)
    ChannelPipeline addFirst(String name, ChannelHandler handler);
    
    // 在指定Handler之前添加
    ChannelPipeline addBefore(String baseName, String name, ChannelHandler handler);
    
    // 在指定Handler之后添加
    ChannelPipeline addAfter(String baseName, String name, ChannelHandler handler);
    
    // 移除Handler
    ChannelPipeline remove(ChannelHandler handler);
    ChannelHandler remove(String name);
    
    // 替换Handler
    ChannelPipeline replace(ChannelHandler oldHandler, String newName, ChannelHandler newHandler);
    
    // 获取Handler
    ChannelHandler get(String name);
    <T extends ChannelHandler> T get(Class<T> handlerType);
    
    // 获取Channel
    Channel channel();
}

3.5.4 Pipeline 使用示例

public class PipelineDemo {
    public static void main(String[] args) throws Exception {
        EventLoopGroup group = new NioEventLoopGroup();
        
        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(group)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) {
                            ChannelPipeline pipeline = ch.pipeline();
                            
                            // 添加Handler(按顺序执行)
                            pipeline.addLast("decoder", new StringDecoder());
                            pipeline.addLast("encoder", new StringEncoder());
                            pipeline.addLast("handler1", new InboundHandler1());
                            pipeline.addLast("handler2", new InboundHandler2());
                            pipeline.addLast("handler3", new OutboundHandler1());
                            
                            // 动态添加Handler
                            if (needAuth) {
                                pipeline.addFirst("auth", new AuthHandler());
                            }
                            
                            // 移除Handler
                            // pipeline.remove("handler1");
                            
                            // 替换Handler
                            // pipeline.replace("handler2", "newHandler", new NewHandler());
                        }
                    });
            
            ChannelFuture future = bootstrap.bind(8080).sync();
            future.channel().closeFuture().sync();
        } finally {
            group.shutdownGracefully();
        }
    }
}

class InboundHandler1 extends ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        System.out.println("InboundHandler1: " + msg);
        ctx.fireChannelRead(msg);  // 传递给下一个入站Handler
    }
}

class InboundHandler2 extends ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        System.out.println("InboundHandler2: " + msg);
        ctx.writeAndFlush("Response: " + msg);  // 触发出站事件
    }
}

class OutboundHandler1 extends ChannelOutboundHandlerAdapter {
    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
        System.out.println("OutboundHandler1: " + msg);
        ctx.write(msg, promise);  // 传递给下一个出站Handler
    }
}

3.5.5 事件传播机制

入站事件传播

// 方式1:从当前Handler传播到下一个Handler
ctx.fireChannelRead(msg);

// 方式2:从Pipeline头部开始传播
ctx.channel().pipeline().fireChannelRead(msg);

出站事件传播

// 方式1:从当前Handler传播到上一个Handler
ctx.write(msg);

// 方式2:从Pipeline尾部开始传播
ctx.channel().write(msg);

3.6 组件协作示例

3.6.1 完整的服务器示例

public class ComponentsServer {
    public static void main(String[] args) throws Exception {
        // 1. 创建EventLoopGroup
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        
        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup)
                    // 2. 指定Channel类型
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) {
                            // 3. 配置Pipeline
                            ChannelPipeline pipeline = ch.pipeline();
                            
                            // 添加编解码器
                            pipeline.addLast(new StringDecoder());
                            pipeline.addLast(new StringEncoder());
                            
                            // 添加业务Handler
                            pipeline.addLast(new ServerHandler());
                        }
                    });
            
            // 4. 绑定端口,返回ChannelFuture
            ChannelFuture future = bootstrap.bind(8080).sync();
            System.out.println("服务器启动成功,监听端口: 8080");
            
            // 5. 添加关闭监听器
            future.channel().closeFuture().addListener((ChannelFutureListener) f -> {
                System.out.println("服务器已关闭");
            });
            
            // 等待服务器关闭
            future.channel().closeFuture().sync();
        } finally {
            // 6. 优雅关闭EventLoopGroup
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

class ServerHandler extends SimpleChannelInboundHandler<String> {
    
    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        // Channel激活
        Channel channel = ctx.channel();
        System.out.println("客户端连接: " + channel.remoteAddress());
        
        // 获取EventLoop
        EventLoop eventLoop = channel.eventLoop();
        System.out.println("绑定的EventLoop: " + eventLoop);
    }
    
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) {
        System.out.println("接收到消息: " + msg);
        
        // 写入数据并添加监听器
        ChannelFuture future = ctx.writeAndFlush("服务器收到: " + msg);
        future.addListener((ChannelFutureListener) f -> {
            if (f.isSuccess()) {
                System.out.println("消息发送成功");
            } else {
                System.out.println("消息发送失败: " + f.cause());
            }
        });
    }
    
    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        System.out.println("客户端断开: " + ctx.channel().remoteAddress());
    }
    
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        System.err.println("发生异常: " + cause.getMessage());
        ctx.close();
    }
}

3.7 本章小结

本章我们深入学习了 Netty 的五大核心组件:

Channel:网络连接的抽象,支持多种传输类型
EventLoop:事件循环,负责处理 I/O 事件和任务调度
ChannelFuture:异步操作的结果占位符
ChannelHandler:处理器,处理 I/O 事件和业务逻辑
ChannelPipeline:处理器链,管理 Handler 的执行顺序

关键要点

  1. Channel 代表一个网络连接,有完整的生命周期
  2. EventLoop 绑定一个线程,一个 EventLoop 可以处理多个 Channel
  3. ChannelFuture 用于异步操作,推荐使用监听器而非阻塞等待
  4. ChannelHandler 分为入站和出站两种,使用 SimpleChannelInboundHandler 可以自动释放消息
  5. ChannelPipeline 是双向链表,入站事件从头到尾,出站事件从尾到头

组件关系图

Channel
    ├── EventLoop (绑定)
    ├── ChannelPipeline (包含)
    │   ├── ChannelHandler 1
    │   ├── ChannelHandler 2
    │   └── ChannelHandler 3
    └── ChannelFuture (操作结果)

下一章预告

下一章我们将学习 Bootstrap 启动器,包括:

  • ServerBootstrap 服务端启动详解
  • Bootstrap 客户端启动详解
  • 启动参数配置
  • 优雅关闭机制

练习题

  1. 基础题:编写一个服务器,打印 Channel 的完整生命周期
  2. 进阶题:实现一个 Pipeline,包含日志、认证、业务处理三个 Handler
  3. 挑战题:使用 EventLoop 实现一个定时任务调度器

上一章第2章:网络编程基础
下一章第4章:Bootstrap启动器