Netty的NioServerSocketChannel源码解析

Netty的NioServerSocketChannel源码解析教程

NioServerSocketChannel 它是服务端连接请求 Channel。它的功能和 JDK 里面的 ServerSocketChannel 相似。

核心方法

newSocket()

private static ServerSocketChannel newSocket(SelectorProvider provider) { try { /** * Use the {@link SelectorProvider} to open {@link SocketChannel} and so remove condition in * {@link SelectorProvider#provider()} which is called by each ServerSocketChannel.open() otherwise. * * See <a href="https://github.com/netty/netty/issues/2308">#2308</a>. */ return provider.openServerSocketChannel(); } catch (IOException e) { throw new ChannelException( "Failed to open a server socket.", e); } }

使用 SelectorProvider 打开 SocketChannel,从而删除 SelectorProvider.provider() 中的条件,否则每个 ServerSocketChannel.open()将调用该条件。

本地实现方法

@Override public boolean isActive() { return javaChannel().socket().isBound(); } @Override public InetSocketAddress remoteAddress() { return null; } @Override protected ServerSocketChannel javaChannel() { return (ServerSocketChannel) super.javaChannel(); } @Override protected SocketAddress localAddress0() { return SocketUtils.localSocketAddress(javaChannel().socket()); } @Override protected void doBind(SocketAddress localAddress) throws Exception { if (PlatformDependent.javaVersion() >= 7) { javaChannel().bind(localAddress, config.getBacklog()); } else { javaChannel().socket().bind(localAddress, config.getBacklog()); } }

通过 java.net.ServerSocket 的 isBound 方法判断服务端监听端口是否处于绑定状态,它的 remoteAddress 为空。javaChannel 的实现是 java.nio. ServerSocketChannel,服务端在进行端口绑定的时候,可以指定backlog,也就是允许客户端排队的最大长度。

doReadMessages()

protected int doReadMessages(List<Object> buf) throws Exception { SocketChannel ch = SocketUtils.accept(javaChannel()); try { if (ch != null) { buf.add(new NioSocketChannel(this, ch)); return 1; } } catch (Throwable t) { logger.warn("Failed to create a new channel from an accepted socket.", t); try { ch.close(); } catch (Throwable t2) { logger.warn("Failed to close a socket.", t2); } } return 0; }

首先通过 javaChannel() 获取一个 ServerSocketChannel 对象,然后通过 SocketUtils.accept 方法接收新的客户端连接,如果 SocketChannel 不为空,则利用当前的NioServerSocketChannel、 EventLoop 和 SocketChannel 创建新的NioSocketChannel,并将其加入到 List buf 中,最后返回 1,表示服务端消息读取成功。

对于 NioServerSocketChannel,它的读取操作就是接收客户端的连接,创建 NioSocketChannel 对象。

服务单Channel无关方法

以下的方法是和客户端 Channel 相关的,服务端如果调用的话,会抛出异常,我们在平时使用时如果误调用,就会发生异常,具体方法如下:

protected boolean doConnect( SocketAddress remoteAddress, SocketAddress localAddress) throws Exception { throw new UnsupportedOperationException(); } @Override protected void doFinishConnect() throws Exception { throw new UnsupportedOperationException(); } @Override protected SocketAddress remoteAddress0() { return null; } @Override protected void doDisconnect() throws Exception { throw new UnsupportedOperationException(); } @Override protected boolean doWriteMessage(Object msg, ChannelOutboundBuffer in) throws Exception { throw new UnsupportedOperationException(); } @Override protected final Object filterOutboundMessage(Object msg) throws Exception { throw new UnsupportedOperationException(); }

Netty的NioServerSocketChannel总结

Netty 的 NioServerSocketChannel 是 Netty 的服务端操作 Channel。它的本质是和 NIO 的 ServerSocketChannel 类似的。