首先我们看一下正常netty服务端启动的代码
public void server(int port) throws Exception {
final ByteBuf buf = Unpooled.copiedBuffer("hello", Charset.forName("UTF-8"));
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
.localAddress(new InetSocketAddress(port)).childHandler(new ChannelInitializer<SocketChannel>(){
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new ChannelInboundHandlerAdapter(){
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// 消息写完关闭连接
ctx.writeAndFlush(buf.duplicate()).addListener(ChannelFutureListener.CLOSE);
}
});
}
});
ChannelFuture f = serverBootstrap.bind().sync();
f.channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully().sync();
workerGroup.shutdownGracefully().sync();
}
}
然后我们从bind()方法跟进去,发现有个doBind()方法,里面有个initAndRegister()方法就是创建服务端Channel的地方,有个
public T newChannel() {
try {
return clazz.newInstance();
} catch (Throwable t) {
throw new ChannelException("Unable to create Channel from class " + clazz, t);
}
}
可以看出是通过反射的方式创建,那么这个clazz怎么来的呢,就是通过serverBootstrap的
channel(NioServerSocketChannel.class)传递进来的,我们再看看这个channel()方法
public B channel(Class<? extends C> channelClass) {
if (channelClass == null) {
throw new NullPointerException("channelClass");
}
return channelFactory(new ReflectiveChannelFactory<C>(channelClass));
}
就是这里把NioServerSocketChannel.class封装到ReflectiveChannelFactory传递给了channelFactory。
接着我们分析NioServerSocketChannel这个类的构造函数做了哪些事情
public NioServerSocketChannel() {
this(newSocket(DEFAULT_SELECTOR_PROVIDER));
}
private static ServerSocketChannel newSocket(SelectorProvider provider) {
try {
return provider.openServerSocketChannel();
} catch (IOException e) {
throw new ChannelException(
"Failed to open a server socket.", e);
}
}
首先是通过newSocket()创建了一个jdk底层的ServerSocketChannel,这里其实就把一个服务端的channel创建完毕了,我们接着看
public NioServerSocketChannel(ServerSocketChannel channel) {
super(null, channel, SelectionKey.OP_ACCEPT);
config = new NioServerSocketChannelConfig(this, javaChannel().socket());
}
这里调用了父类的构造函数、NioServerSocketChannelConfig进行tcp参数配置,我们跟着这个父类构造函数
protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
super(parent);
this.ch = ch;
this.readInterestOp = readInterestOp;
try {
// 设置服务端channle为非阻塞模式
ch.configureBlocking(false);
} catch (IOException e) {
try {
ch.close();
} catch (IOException e2) {
if (logger.isWarnEnabled()) {
logger.warn(
"Failed to close a partially initialized socket.", e2);
}
}
throw new ChannelException("Failed to enter non-blocking mode.", e);
}
}
通过 ch.configureBlocking(false);设置服务端channle为非阻塞模式,我们接着父类构造函数往下跟
protected AbstractChannel(Channel parent) {
this.parent = parent;
id = newId();
unsafe = newUnsafe();
pipeline = newChannelPipeline();
}
通过AbstractChannel,创建id(channel 的id),unsafe(channel底层tcp读写操作的一个类),pipeline(channel事件处理的一条链)。
到这里,服务端channle的创建源码解析就已经结束。