# ai-netty **Repository Path**: idea360/ai-netty ## Basic Information - **Project Name**: ai-netty - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-09-11 - **Last Updated**: 2025-09-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # ai-netty 简化版 Netty 实现 本项目基于 Java NIO 实现了一个可运行的简化版 Netty,用于学习 Netty 的核心原理与主要设计。包含服务器与客户端 Echo 示例,可直接运行验证事件循环、管道、编解码与 NIO 通道的协作。 ## 快速开始 - 构建 ```bash mvn -q -DskipTests package ``` - 运行 EchoServer(一个终端): ```bash java -cp target/classes cn.idea360.netty.example.EchoServer ``` - 运行 EchoClient(另一个终端): ```bash java -cp target/classes cn.idea360.netty.example.EchoClient ``` 你应当在客户端看到 `Echo: Hello Netty!`,在服务端/日志里看到相应日志与收发。 ## 核心模块与设计 - Channel(`cn.idea360.netty.channel.Channel`) - 抽象底层网络通道(ServerSocketChannel / SocketChannel)。 - 提供 `bind/close/pipeline/eventLoop/writeAndFlush` 基础能力。 - Pipeline & Handler(`DefaultChannelPipeline`、`ChannelHandler`、`DefaultChannelHandlerContext`) - 双向链表结构的管道,head/tail + 用户自定义处理器。 - 入站事件从 head 向 tail 传播;本实现将出站简化为直接调用 `Channel.writeAndFlush`。 - `LoggingHandler`、`StringDecoder`、`StringEncoder` 作为示例处理器。 - EventLoop(`NioEventLoop`、`NioEventLoopGroup`) - 单线程 selector 事件循环,维护任务队列(`execute` 跨线程投递)。 - 处理 `OP_ACCEPT/OP_READ/OP_WRITE`。通过 `enableWrite/disableWrite` 控制写事件避免空转。 - Group 负责创建并复用若干 EventLoop 实例。 - NIO 通道(`NioChannel`、`NioSocketChannel`) - `NioChannel` 封装 `ServerSocketChannel`:bind 后注册 `OP_ACCEPT`。 - `NioSocketChannel` 封装 `SocketChannel`:注册 `OP_READ`;`write` 入队并打开 `OP_WRITE`;在 `flush` 中尽可能写完并按需关闭 `OP_WRITE`。 - ByteBuf(`buffer/ByteBuf`) - 提供基本的可扩容字节缓冲与读写索引(已具备核心功能,可按需扩展 API)。 ## 数据流与事件流(简版) 1. 服务器通过 `NioChannel.bind` → EventLoop 注册 `OP_ACCEPT`。 2. 有新连接时,`NioEventLoop` 接受连接并创建 `NioSocketChannel`,注册 `OP_READ` 并触发 `channelActive`。 3. 可读时,`NioSocketChannel.read` 读取字节并 `pipeline.fireChannelRead(bytes)`。 4. 编解码器在入站方向处理消息(`StringDecoder` 将 `byte[]` → `String`)。 5. 业务 Handler 收到字符串后调用 `ctx.writeAndFlush("...")` 触发出站写。 6. `NioSocketChannel.write` 将消息入队并开启 `OP_WRITE`;在 `flush`(写就绪)时写出并按需关闭 `OP_WRITE`。 ## 与 Netty 正式版的取舍 - 缺少完整的出站链路与 ChannelPromise/ChannelFuture 完整语义。 - 未实现复杂的线程亲和、内存池、零拷贝、背压、流水线化 promise 等。 - 保留核心骨架:事件循环、选择器、通道封装、管道/处理器、基础编解码。 ## 目录导航 - `cn.idea360.netty.channel`:Channel 接口与 NIO 实现、Pipeline/Context - `cn.idea360.netty.eventloop`:NIO 事件循环与分组 - `cn.idea360.netty.handler`:示例编解码器与日志处理器 - `cn.idea360.netty.buffer`:简化版 ByteBuf - `cn.idea360.netty.example`:EchoServer 与 EchoClient 示例 ## 扩展建议 - 完整实现出站链与 `ChannelPromise/ChannelFuture`。 - 增加 `Bootstrap/ServerBootstrap` 以统一启动流程与选项配置。 - 扩展 `ByteBuf` API(read/write 基本类型、slice/duplicate、reference count)。 - 增加心跳/空闲检测、半包粘包解码器、长度字段帧解码等。 ## 时序图与时序日志 ### 1) 服务端 Echo 交互时序图(Mermaid) ```mermaid sequenceDiagram participant Client as EchoClient participant CCh as NioSocketChannel(客户端) participant CLoop as NioEventLoop(客户端) participant Srv as NioChannel(服务端) participant SLoop as NioEventLoop(服务端) participant SAcpt as ServerSocketChannel participant SCh as NioSocketChannel(子通道) participant SPipe as Pipeline(子通道) Note over Srv: bind(8080) → register OP_ACCEPT Srv->>SLoop: execute(bind) SLoop->>SAcpt: register OP_ACCEPT(att=Srv) Note over Client: 连接到服务器 Client->>CCh: SocketChannel.connect() CCh->>CLoop: register OP_READ Note over SLoop: 有新连接可接受 SLoop->>SAcpt: accept() SLoop->>SCh: new NioSocketChannel + register OP_READ Srv-->>SCh: childHandler.initChannel(安装 StringDecoder/Logging/EchoHandler) SCh->>SPipe: fireChannelActive Note over Client: 发送请求 Client->>CCh: writeAndFlush("Hello Netty!") CCh->>CLoop: enable OP_WRITE CLoop-->>CCh: flush() 写入字节 Note over SCh: 可读事件到达 SLoop-->>SCh: read() 得到 byte[] SCh->>SPipe: fireChannelRead(byte[]) SPipe->>SPipe: StringDecoder 将 byte[] → String SPipe->>SPipe: LoggingHandler 打印 SPipe->>SPipe: EchoServerHandler 收到 "Hello Netty!" EchoServerHandler->>SCh: ctx.writeAndFlush("Echo: Hello Netty!") SCh->>SLoop: enable OP_WRITE → flush() Note over CCh: 客户端可读 CLoop-->>CCh: read() 得到 byte[] CCh->>Client: 解码后回调 EchoClientHandler("Echo: Hello Netty!") ``` ### 2) 一次典型交互的时序日志(示例) 服务器终端: ```text Echo server started on port 8080 [LOG] channelActive [LOG] channelRead: Hello Netty! Server received: Hello Netty! ``` 客户端终端: ```text [LOG] channelActive [LOG] channelRead: Echo: Hello Netty! Client received: Echo: Hello Netty! ``` ## 架构设计与运行原理(汇总) ### 组件职责 - Channel:抽象底层连接,提供 `bind/close/pipeline/eventLoop/writeAndFlush`。`NioChannel` 封装 `ServerSocketChannel`,`NioSocketChannel` 封装 `SocketChannel`。 - EventLoop:单线程 Selector 事件循环,负责 select 轮询与任务队列执行(`execute` 跨线程投递)。 - Pipeline/Handler/Context:双向链表的处理器链,入站事件从 head → tail 传播;本实现将出站简化为直接调用 `Channel.writeAndFlush`。 - ChannelInitializer:在服务端 `accept` 后,为每个子连接初始化处理器链(childHandler)。 - ByteBuf:可扩容字节缓冲,提供基础读写能力。 ### 线程与事件模型 - 每个 `NioEventLoop` 拥有一个 Selector 与一个专属线程;所有 IO 与事件回调在该线程内执行,避免锁竞争。 - `execute(Runnable)` 将外部线程的任务安全地投递到事件循环线程执行;首次 `execute` 会启动事件循环主方法 `run()`。 - 处理的 IO 事件:`OP_ACCEPT`(新连接)、`OP_READ`(可读)、`OP_WRITE`(可写)。通过 `enableWrite/disableWrite` 动态开关写兴趣,避免空转。 ### 连接建立流程(服务端) 1) `NioChannel.bind(port)` 在事件循环线程中绑定端口,并注册 `OP_ACCEPT`(将 `NioChannel` 作为 attachment)。 2) 有新连接到达时,`accept()` 创建 `SocketChannel`,封装为 `NioSocketChannel` 并注册 `OP_READ`。 3) 若配置了 `childHandler(ChannelInitializer)`,则对该子通道调用 `initChannel` 安装 `StringDecoder/LoggingHandler/EchoServerHandler` 等。 4) 触发子通道 `channelActive`,即可收发数据。 ### 数据流(入站) 1) `NioSocketChannel.read()` 读到 `byte[]` → `pipeline.fireChannelRead(byte[])`。 2) `StringDecoder` 将 `byte[]` → `String`,继续透传。 3) `LoggingHandler` 打印后透传。 4) 业务 Handler(如 Echo)拿到字符串并处理。 ### 数据流(出站,简化实现) - 本实现暂未构建完整“出站链”。当业务调用 `ctx.writeAndFlush(String)` 时: - `DefaultChannelHandlerContext` 直接调用 `channel.writeAndFlush`。 - `NioSocketChannel.write` 将 `String` 转成 UTF-8 字节入队,开启 `OP_WRITE`;在 `flush`(写就绪)时尽可能写完,若队列空则关闭 `OP_WRITE`。 ### 与 Netty 正式版的取舍 - 出站链、`ChannelPromise/ChannelFuture`、零拷贝与内存池、背压等特性在本项目中做了简化,以突出核心骨架(事件循环、管道、通道封装、编解码)。 - 可以按需将 `StringEncoder` 放入出站链并补全出站传播、Promise 完成回调等,以逐步逼近 Netty 语义。