[Netty] 서버 시작

27644 단어 Netty

1. 서버 부팅 코드

public static void main(String[] args) throws Exception {
        //     .
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        //     .
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childOption(ChannelOption.TCP_NODELAY, true)
                    .childAttr(AttributeKey.newInstance("childAttr"), "childAttrValue")
                    .handler(new ServerHandler())
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) {
                            ch.pipeline().addLast(new AuthHandler());
                            //..

                        }
                    });
            //   .
            ChannelFuture f = b.bind(8888).sync();

            f.channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

Bind 메서드에 들어가면 다음과 같은 이점을 얻을 수 있습니다.
private ChannelFuture doBind(final SocketAddress localAddress) {
//       .
final ChannelFuture regFuture = this.initAndRegister();
//     .
ChannelPromise promise = channel.newPromise();
doBind0(regFuture, channel, localAddress, promise);
}

2. 초기화 및 등록

final ChannelFuture initAndRegister() {```
...
//   1:  channel.
channel = this.channelFactory.newChannel();
//   2:   channel
this.init(channel);
//   3:  .
ChannelFuture regFuture = this.config().group().register(channel);
}

(1) 채널 만들기

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

private static java.nio.channels.ServerSocketChannel newSocket(SelectorProvider provider) {
        try {
            return provider.openServerSocketChannel();
        } catch (IOException var2) {
            throw new ChannelException("Failed to open a server socket.", var2);
        }
    }

public NioServerSocketChannel(java.nio.channels.ServerSocketChannel channel) {
        //              .
        super((Channel)null, channel, 16);
        this.config = new NioServerSocketChannel.NioServerSocketChannelConfig(this, this.javaChannel().socket());
    }

채널 초기화


주로 채널 관련 속성을 설정하고 pipeline을 설정하며 ServerBootstrapAcceptor를 추가합니다
void init(Channel channel) throws Exception {
// options  
channel.config().setOptions(options);
...
// 
channel.config().setOptions(options);
...
//
currentChildOptions = (Entry[])this.childOptions.entrySet().toArray(newOptionArray(this.childOptions.size()));
...
//
currentChildAttrs = (Entry[])this.childAttrs.entrySet().toArray(newAttrArray(this.childAttrs.size()));
...
//   ServerBootstrapAcceptor.
pipeline.addLast(new ChannelHandler[]{new ServerBootstrap.ServerBootstrapAcceptor(currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs)});
...
}

(3) 등록


3. 포트 바인딩

private static void doBind0(final ChannelFuture regFuture, final Channel channel, final SocketAddress localAddress, final ChannelPromise promise) {
        channel.eventLoop().execute(new Runnable() {
            public void run() {
                if (regFuture.isSuccess()) {
                //     
                    channel.bind(localAddress, promise).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
                } else {
                    promise.setFailure(regFuture.cause());
                }

            }
        });
    }

//서버 channel 만들기//서버 channel 초기화//등록selector//포트 귀속




         
```java
ChannelFuture regFuture = this.config().group().register(channel);

//실제 등록, 중요this.register0(promise); …
}
실제 등록
       private void register0(ChannelPromise promise) {
...
  AbstractChannel.this.doRegister();
     AbstractChannel.this.pipeline.invokeHandlerAddedIfNeeded();
          AbstractChannel.this.pipeline.fireChannelRegistered();

...
}
    protected void doRegister() throws Exception {
        boolean selected = false;

        while(true) {
            try {
            //    jdk    . 0         .this    channel attachment,   selector   ,   select       ,   this     ,4、44s
                this.selectionKey = this.javaChannel().register(this.eventLoop().selector, 0, this);
                return;
            } catch (CancelledKeyException var3) {
                if (selected) {
                    throw var3;
                }

                this.eventLoop().selectNow();
                selected = true;
            }
        }
    }


포트 바인딩:
dobindjavachannel을 연결해서 채널을 건드리도록 전파합니다.read 이벤트, 서버에서 새로운 연결을 읽을 수 있습니다

좋은 웹페이지 즐겨찾기