NioServerSocketChannel 它是服务端连接请求 Channel。它的功能和 JDK 里面的 ServerSocketChannel 相似。
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,也就是允许客户端排队的最大长度。
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
对于 NioServerSocketChannel,它的读取操作就是接收客户端的连接,创建 NioSocketChannel 对象。
以下的方法是和客户端 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 的服务端操作 Channel。它的本质是和 NIO 的 ServerSocketChannel 类似的。