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;
    	}
    }
}

image-20251127173616468

[你的业务 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 发送),但体验和效率大不相同。

posted @ 2025-11-27 20:28  deyang  阅读(11)  评论(0)    收藏  举报