Netty server Startup (1) creates and initializes a channel
Register the selector
To summarize, we have done these things
- Setting up eventLoop (for thread binding)
- Call the register method of the underlying SelectableChannel class in the JDK to register
- Trigger a callback added to a channel by a handler that triggers a channel registration success event
The process of registering a selector is in the register method on the config().group().register(channel) line, which eventually calls the AbstractChannel#register method
public final void register(EventLoop eventLoop, final ChannelPromise promise) {
ObjectUtil.checkNotNull(eventLoop, "eventLoop");
// Omit some code
AbstractChannel.this.eventLoop = eventLoop;
if (eventLoop.inEventLoop()) { register0(promise); } else { try { eventLoop.execute(new Runnable() { @Override public void run(a) { register0(promise); } }); } catch (Throwable t) { / / to omit } } } Copy the code
As you can see, you’re setting up the EventLoop (for binding threads), and look at the method register0 that actually registers
private void register0(ChannelPromise promise) {
try {
if(! promise.setUncancellable() || ! ensureOpen(promise)) { return;
} //neverRegistered starts with true boolean firstRegistration = neverRegistered; doRegister(); neverRegistered = false; registered = true; // Triggers a callback when a handler is added to a channel pipeline.invokeHandlerAddedIfNeeded(); safeSetSuccess(promise); // Propagate the channel registration success event pipeline.fireChannelRegistered(); if (isActive()) { / / to omit } } catch (Throwable t) { / / to omit } } Copy the code
As you can see, the doRegister method is called, and the AbstractNioChannel#doRegister method is called
protected void doRegister(a) throws Exception {
boolean selected = false;
for (;;) {
try {
//javaChannel() returns the Java underlying SelectableChannel
// The register method binds netty's channel to the underlying JDK channel as an attachment selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0.this); return; } catch (CancelledKeyException e) { / / to omit } } } Copy the code
As you can see, this is a call to the Java underlying method to register
Port binding
To summarize, we have done the following things
- Call the JDK’s underlying bind method for port binding
- The channelActive event is triggered
- Trigger the read event, register the Accept event with selector
Port binding is in the AbstractBootstrap#doBind0 method
private static void doBind0(
final ChannelFuture regFuture, final Channel channel,
final SocketAddress localAddress, final ChannelPromise promise) {
channel.eventLoop().execute(new Runnable() {
@Override public void run(a) { if (regFuture.isSuccess()) { channel.bind(localAddress, promise).addListener(ChannelFutureListener.CLOSE_ON_FAILURE); } else { promise.setFailure(regFuture.cause()); } } }); } Copy the code
This is where you end up calling the AbstractChannel#bind method
public final void bind(final SocketAddress localAddress, final ChannelPromise promise) {
assertEventLoop();
// Omit some code
boolean wasActive = isActive(); try { // Call the underlying JDK for binding doBind(localAddress); } catch (Throwable t) { safeSetFailure(promise, t); closeIfClosed(); return; } if(! wasActive && isActive()) { invokeLater(new Runnable() { @Override public void run(a) { // Send the channelActive event pipeline.fireChannelActive(); } }); } safeSetSuccess(promise); } Copy the code
Following the doBind method, the NioServerSocketChannel#doBind method is called
protected void doBind(SocketAddress localAddress) throws Exception {
if (PlatformDependent.javaVersion() >= 7) {
javaChannel().bind(localAddress, config.getBacklog());
} else {
javaChannel().socket().bind(localAddress, config.getBacklog());
} } Copy the code
You can see that you are calling the underlying JDK bind method
FireChannelActive finally calls the DefaultChannelPipeline#channelActive method
public void channelActive(ChannelHandlerContext ctx) {
ctx.fireChannelActive();
readIfIsAutoRead();
}
Copy the code
The AbstractNioChannel#doBeginRead method is called by the readIfIsAutoRead method
protected void doBeginRead(a) throws Exception {
// Channel.read() or ChannelHandlerContext.read() was called
final SelectionKey selectionKey = this.selectionKey;
if(! selectionKey.isValid()) { return;
} readPending = true; final int interestOps = selectionKey.interestOps(); if ((interestOps & readInterestOp) == 0) { selectionKey.interestOps(interestOps | readInterestOp); } } Copy the code
As you can see, we’re registering the accept event with the selector. (See the previous NioServerSocketChannel constructor passed selectionkey.op_accept.)