Netty读写
目录
Netty读写
连接保存的地方
Netty Server Main
└── serverChannel (手动保存引用)
└── Boss EventLoop (通常1个)
├── Selector
│ └── SelectionKey (attachment: NioServerSocketChannel)
└── registeredChannels: [NioServerSocketChannel]
NioServerSocketChannel
↓ 创建关系
NioSocketChannel A ──→ Worker EventLoop 1
├── Selector: [SelectionKey(attachment: ChannelA)]
└── registeredChannels: [ChannelA, ChannelB, ...]
NioServerSocketChannel和NioSocketChannel都继承自AbstractNioChannel
abstract class AbstractNioChannel extends AbstractChannel{
// 核心:保存 Java NIO 的原始通道
// NioSocketChannel就是SocketChannel
// NioServerSocketChannel就是ServerSocketChannel
private final SelectableChannel ch;
// 这个通道的感兴趣事件(OP_READ, OP_ACCEPT 等)
protected final int readInterestOp;
AbstractChannel {
// NioServerSocketChannel:这种通道的 parent 是 null,因为它是顶层通道
// NioSocketChannel:这种通道的 parent 指向创建它的 ServerSocketChannel
private final Channel parent;
private final DefaultChannelPipeline pipeline;
DefaultChannelPipeline {
// HeadContext ↔ Handler1 ↔ Handler2 ↔ ... ↔ TailContext (双向链表)
final AbstractChannelHandlerContext head;
final AbstractChannelHandlerContext tail;
// 这个channel字段指向的是这个pipeline所服务的Channel AbstractNioChannel是什么这个channel就是什么
private final Channel channel;
}
}
}

[你的业务 Handler]
↓
Netty: ChannelPipeline → encode/write/flush
↓
Netty: HeadContext → encode/write/flush → unsafe.encode/write/flush #[这个Unsafe是netty自己定义的]
↓
Netty: NioSocketChannel.Unsafe.doWrite() / doRead() #NioSocketChannel是netty实现的socket
↓
JDK: SocketChannel.write(ByteBuffer) / read(ByteBuffer) #Netty的AbstractNioChannel的SelectableChannel ch;字段
↓
JVM: JNI 调用 native C 代码(如 IOUtil.write)→ writeFromNativeBuffer(var0, var1, var2, var4) → var4.write
→ SocketDispatcher.write → native int write0
↓
操作系统: write() / send() / recv() 系统调用
↓
TCP/IP 协议栈 → 网卡发送/接收数据包
Java BIO读写:默认全程阻塞,性能较低(每次调用需 JVM 拷贝数组)
- UDP:DatagramSocketImpl类的receive(DatagramPacket p)和send(DatagramPacket p)
- TCP:SocketOutputStream类的socketWrite0、SocketInputStream类的socketRead0
Java NIO读写:可配置为非阻塞,性能更高(可使用 DirectBuffer 零拷贝)
-
DatagramDispatcher、SocketDispatcher、FileDispatcherImpl分别是对应udp、tcp、文件
-
IOUtil类里面的读写方法
JNI 调用 native C 代码(如 IOUtil.write)→ writeFromNativeBuffer(var0, var1, var2, var4) → var4.write → SocketDispatcher.write → native int write0
总结:一条走的是现代高速(NIO + ByteBuffer + 零拷贝), 一条走的是老国道(BIO + byte[] + 同步阻塞)。 目的地相同(操作系统 socket 发送),但体验和效率大不相同。
浙公网安备 33010602011771号