020_对照原生NIO代码看看Netty如何创建ServerSocketChannel

1、服务端初始化代码

ServerBootstrap serverBootstrap = new ServerBootstrap(); // 相当于Netty的服务器
			
serverBootstrap
			.group(parentGroup, childGroup)
			.channel(NioServerSocketChannel.class)  // 监听端口的ServerSocketChannel
			.option(ChannelOption.SO_BACKLOG, 1024)
			.childHandler(new ChannelInitializer<SocketChannel>() { // 处理每个连接的SocketChannel

				@Override
				protected void initChannel(SocketChannel socketChannel) throws Exception {
					socketChannel.pipeline().addLast(new NettyServerHandler()); // 针对网络请求的处理逻辑
				}
				
			});
	
	ChannelFuture channelFuture = serverBootstrap.bind(50070).sync(); // 同步等待启动服务器监控端口
	
	channelFuture.channel().closeFuture().sync(); // 同步等待关闭启动服务器的结果

点击上面的bind方法,进入如下代码

public ChannelFuture bind(int inetPort) {
    return bind(new InetSocketAddress(inetPort));
}

通过端口号创建一个 InetSocketAddress,继续

public ChannelFuture bind(SocketAddress localAddress) {
    validate();
    return doBind(ObjectUtil.checkNotNull(localAddress, "localAddress"));
}

点击doBind,

private ChannelFuture doBind(final SocketAddress localAddress) {
     final ChannelFuture regFuture = initAndRegister();
     final Channel channel = regFuture.channel();
   //省略
   //。。。。
}

点击initAndRegister方法

final ChannelFuture initAndRegister() {
    Channel channel = null;
	try {
	            channel = channelFactory.newChannel();
	            init(channel);
	 } catch (Throwable t) {
	           //省略
	   //。。。。
}

点击newChannel方法,进入ReflectiveChannelFactory类

@Override
    public T newChannel() {
        try {
            return constructor.newInstance();
        } catch (Throwable t) {
            throw new ChannelException("Unable to create Channel from class " + constructor.getDeclaringClass(), t);
        }
    }

看到这个我们就知道Channel是通过constructor.newInstance()构造的。而constructor的初始化代码如下:

private final Constructor<? extends T> constructor;

    public ReflectiveChannelFactory(Class<? extends T> clazz) {
        ObjectUtil.checkNotNull(clazz, "clazz");
        try {
            this.constructor = clazz.getConstructor();
        } catch (NoSuchMethodException e) {
            throw new IllegalArgumentException("Class " + StringUtil.simpleClassName(clazz) +
                    " does not have a public non-arg constructor", e);
        }
    }

看到这里我们就明白了Channel是通过反射创建出来的,是根据我们传入的要给类去拿到默认的构造函数创建。那我们在初始化的时候只在如下这个地方传了个类进去

.channel(NioServerSocketChannel.class)  // 监听端口的ServerSocketChannel

所以应该是调用NioServerSocketChannel类的默认构造函数来创建Channel。

NioServerSocketChannel类

public NioServerSocketChannel() {
        this(newSocket(DEFAULT_SELECTOR_PROVIDER));
    }

其中DEFAULT_SELECTOR_PROVIDER如下:

private static final SelectorProvider DEFAULT_SELECTOR_PROVIDER = SelectorProvider.provider();

点击newSocket方法进入如下:

private static ServerSocketChannel newSocket(SelectorProvider provider) {
    //省略...
    return provider.openServerSocketChannel();
}

通过SelectorProvider.openServerSocketChannel()创建一条ServerSocketChannel 。
构造器继续往下

public NioServerSocketChannel(ServerSocketChannel channel) {
    super(null, channel, SelectionKey.OP_ACCEPT);
    config = new NioServerSocketChannelConfig(this, javaChannel().socket());
}

代码太长了,先就不慢慢记录了。可以参考这篇文章

https://www.jianshu.com/p/c5068caab217
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值