Netty análisis de código fuente de las cuatro series: Netty de comenzar a crear NioServerSocketChannel

introducción

Último artículo principalmente Nettyproceso de inicio, la participación de los NioEventLoopGroupdetalles relevantes se describen en detalle, este artículo se presentan una serie de otros pasos de inicialización de arranque.

  • Channelproceso de creación e inicialización
  • resumen

En primer lugar, el Channelproceso de creación e inicialización

ChannelEs Nettypara se implementa la capa de abstracción de red, que puede corresponder a JDKla NIOaplicación del paquete, Nettyel lado del servicio de Channeltipo NioServerSocketChannel. Para analizar la siguiente NioServerSocketChannelcreado e inicializado.

1, Port Binding

Durante la operación de inicio es un enlace importante puerto, y NioServerSocketChannella creación se lleva a cabo en este proceso. ServerBootStrapel bind()método

ChannelFuture f = b.bind(PORT).sync();

Ver el código fuente correspondiente, la llamada real es AbstractBootstrapla clase bindmétodo:

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

 public ChannelFuture bind(SocketAddress localAddress) {
        validate();
        return doBind(ObjectUtil.checkNotNull(localAddress, "localAddress"));
    }
...
 private ChannelFuture doBind(final SocketAddress localAddress) {
 		//初始化channel
        final ChannelFuture regFuture = initAndRegister();
        final Channel channel = regFuture.channel();
        if (regFuture.cause() != null) {
            return regFuture;
        }
		//若注册成功,则进行bind操作
        if (regFuture.isDone()) {
            // At this point we know that the registration was complete and successful.
            ChannelPromise promise = channel.newPromise();
            doBind0(regFuture, channel, localAddress, promise);
            return promise;
        } else {
            // Registration future is almost always fulfilled already, but just in case it's not.
            final PendingRegistrationPromise promise = new PendingRegistrationPromise(channel);
            regFuture.addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    Throwable cause = future.cause();
                    if (cause != null) {
                        // Registration on the EventLoop failed so fail the ChannelPromise directly to not cause an
                        // IllegalStateException once we try to access the EventLoop of the Channel.
                        promise.setFailure(cause);
                    } else {
                        // Registration was successful, so set the correct executor to use.
                        // See https://github.com/netty/netty/issues/2586
                        promise.registered();

                        doBind0(regFuture, channel, localAddress, promise);
                    }
                }
            });
            return promise;
        }
    }

2. CrearNioServerSocketChannel

initAndRegister()Completado NioServerSocketChannella inicialización y registro de la operación, después de la inicialización y el registro es completa, la operación de unión real, seguimos mirando hacia abajo:

final ChannelFuture initAndRegister() {
        Channel channel = null;
        try {
        	//channel工厂创建新的channel
            channel = channelFactory.newChannel();
            //初始化channel
            init(channel);
        } catch (Throwable t) {
            if (channel != null) {
                // channel can be null if newChannel crashed (eg SocketException("too many open files"))
                channel.unsafe().closeForcibly();
                // as the Channel is not registered yet we need to force the usage of the GlobalEventExecutor
                return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t);
            }
            // as the Channel is not registered yet we need to force the usage of the GlobalEventExecutor
            return new DefaultChannelPromise(new FailedChannel(), GlobalEventExecutor.INSTANCE).setFailure(t);
        }
		//注册channel
        ChannelFuture regFuture = config().group().register(channel);
        if (regFuture.cause() != null) {
            if (channel.isRegistered()) {
                channel.close();
            } else {
                channel.unsafe().closeForcibly();
            }
        }

        // If we are here and the promise is not failed, it's one of the following cases:
        // 1) If we attempted registration from the event loop, the registration has been completed at this point.
        //    i.e. It's safe to attempt bind() or connect() now because the channel has been registered.
        // 2) If we attempted registration from the other thread, the registration request has been successfully
        //    added to the event loop's task queue for later execution.
        //    i.e. It's safe to attempt bind() or connect() now:
        //         because bind() or connect() will be executed *after* the scheduled registration task is executed
        //         because register(), bind(), and connect() are all bound to the same thread.

        return regFuture;
    }

La creación de channella llamada real es ReflectiveChannelFactoryen el newChannelmétodo.

public class ReflectiveChannelFactory<T extends Channel> implements ChannelFactory<T> {

	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);
        }
    }
    
  	@Override
    public T newChannel() {
        try {
            return constructor.newInstance();
        } catch (Throwable t) {
            throw new ChannelException("Unable to create Channel from class " + constructor.getDeclaringClass(), t);
        }
    }
...
}

De lo anterior se puede ver el código, clazz.getConstructor().newInstance()creado por medio de la reflexión Channel.

ChannelUna vez creada, lleve a cabo Channella operación de inicialización,

 @Override
    void init(Channel channel) {
    	//设置channle选项
        setChannelOptions(channel, options0().entrySet().toArray(newOptionArray(0)), logger);
        //设置channel属性
        setAttributes(channel, attrs0().entrySet().toArray(newAttrArray(0)));

        ChannelPipeline p = channel.pipeline();

        final EventLoopGroup currentChildGroup = childGroup;
        final ChannelHandler currentChildHandler = childHandler;
        final Entry<ChannelOption<?>, Object>[] currentChildOptions =
                childOptions.entrySet().toArray(newOptionArray(0));
        final Entry<AttributeKey<?>, Object>[] currentChildAttrs = childAttrs.entrySet().toArray(newAttrArray(0));

        p.addLast(new ChannelInitializer<Channel>() {
            @Override
            public void initChannel(final Channel ch) {
                final ChannelPipeline pipeline = ch.pipeline();
                ChannelHandler handler = config.handler();
                if (handler != null) {
                    pipeline.addLast(handler);
                }

                ch.eventLoop().execute(new Runnable() {
                    @Override
                    public void run() {
                        pipeline.addLast(new ServerBootstrapAcceptor(
                                ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
                    }
                });
            }
        });
    }

En segundo lugar, el resumen

Este documento describe NioServerSocketChannelel proceso de creación y análisis de código fuente, explica más adelante en el artículo continúe funcionando después de crear el canal, tales como la espera de una conexión, y así sucesivamente.

发布了88 篇原创文章 · 获赞 49 · 访问量 10万+

Supongo que te gusta

Origin blog.csdn.net/Diamond_Tao/article/details/104132472
Recomendado
Clasificación