持续更新...
此笔记为个人学习netty源码后记录所得,如有错漏烦请见谅;
学习资源B站:黑马程序员Netty全套教程,全网最全Netty深入浅出教程,Java网络编程的王者_哔哩哔哩_bilibili
一、启动流程
1.new InetSocketAddress()
根据ip和端口创建SocketAddress对象,当我们只穿了端口没传ip时,这里获取当前主机的ip;
/**
* ServerBootstrap.bind();服务器绑定端口
*/
public ChannelFuture bind(int inetPort) {
return bind(new InetSocketAddress(inetPort));
}
public InetSocketAddress(int port) {
this(InetAddress.anyLocalAddress(), port);
}
static InetAddress anyLocalAddress() {
return impl.anyLocalAddress();
}
ipv4:
public synchronized InetAddress anyLocalAddress() {
if (anyLocalAddress == null) {
anyLocalAddress = new Inet4Address(); // {0x00,0x00,0x00,0x00}
anyLocalAddress.holder().hostName = "0.0.0.0";
}
return anyLocalAddress;
}
ipv6:
public synchronized InetAddress anyLocalAddress() {
if (anyLocalAddress == null) {
if (InetAddress.preferIPv6Address) {
anyLocalAddress = new Inet6Address();
anyLocalAddress.holder().hostName = "::";
} else {
anyLocalAddress = (new Inet4AddressImpl()).anyLocalAddress();
}
}
return anyLocalAddress;
}
public InetSocketAddress(InetAddress addr, int port) {
holder = new InetSocketAddressHolder(
null,
addr == null ? InetAddress.anyLocalAddress() : addr,
checkPort(port));
}
2.init & register regFuture 处理
final ChannelFuture initAndRegister() {
Channel channel = null;
try {
// 2.1.1这个channelFactory就是我们构建BootStrape时传的NioServerSocketChannel.class
channel = channelFactory.newChannel();
// 2.1.2 初始化channel
init(channel);
} catch (Throwable t) {
if (channel != null) {
channel.unsafe().closeForcibly();
return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t);
}
return new DefaultChannelPromise(new FailedChannel(), GlobalEventExecutor.INSTANCE).setFailure(t);
}
// 2.2 register
ChannelFuture regFuture = config().group().register(channel);
if (regFuture.cause() != null) {
if (channel.isRegistered()) {
channel.close();
} else {
channel.unsafe().closeForcibly();
}
}
return regFuture;
}
2.1 init
2.1.1 创建NioSeverSocketChannel
channelFactory.newChannel()一路看下去,最终使用的时NioServerSocketChannel的构造方法创建的,与ServerSocketChannel.open()一样;
// 上面的channelFactory.newChannel()最终使用的是这个构造方法
public NioServerSocketChannel() {
SelectorProvider.provider();
}
2.1.2 添加NioServerSocketChannel初始化handler
向ServerSocketChannel添加初始化的handler并等待调用,如acceptor handler(在accept事件发生后建立连接);ps:这里的handler都是在事件发生后才调用的,如事件不发生则不会触发;
@Override
void init(Channel channel) {
setChannelOptions(channel, newOptionsArray(), logger);
setAttributes(channel, newAttributesArray());
ChannelPipeline p = channel.pipeline();
final EventLoopGroup currentChildGroup = childGroup;
final ChannelHandler currentChildHandler = childHandler;
final Entry<ChannelOption<?>, Object>[] currentChildOptions = newOptionsArray(childOptions);
final Entry<AttributeKey<?>, Object>[] currentChildAttrs = newAttributesArray(childAttrs);
p.addLast(new ChannelInitializer<Channel>() {
@Override
public void initChannel(final Channel ch) {
final ChannelPipeline pipeline = ch.pipeline();
// 启动时这个handler是空的
ChannelHandler handler = config.handler();
if (handler != null) {
pipeline.addLast(handler);
}
ch.eventLoop().execute(new Runnable() {
@Override
public void run() {
// 添加一个acceptorhandler,等待accept事件触发后调用
pipeline.addLast(new ServerBootstrapAcceptor(
ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
}
});
}
});
}
2.2 register
2.2.1 通过AtomicInteger自增再与执行器求模轮询处理
@Override
public ChannelFuture register(Channel channel) {
return next().register(channel);
}
private final AtomicInteger idx = new AtomicInteger();
private final EventExecutor[] executors;
@Override
public EventExecutor next() {
return executors[idx.getAndIncrement() & executors.length - 1];
}
2.2.2 register
启动nio boss线程;
原生ssc注册至selector未关注事件;
执行NioServerSocketChannel初始化handler;
@Override
public final void register(EventLoop eventLoop, final ChannelPromise promise) {
// 判断是否已注册
if (isRegistered()) {
return;
}
// 判断eventLoop是否属于NioEventLoop
if (!isCompatible(eventLoop)) {
return;
}
AbstractChannel.this.eventLoop = eventLoop;
// 如果当前线程已绑定eventLoop,那么直接使用当前线程执行,启动流程这里为false
if (eventLoop.inEventLoop()) {
register0(promise);
} else {
try {
// 启动一个新的线程(nio boss)
eventLoop.execute(new Runnable() {
@Override
public void run() {
register0(promise);
}
});
} catch (Throwable t) {
closeForcibly();
closeFuture.setClosed();
safeSetFailure(promise, t);
}
}
}
private void register0(ChannelPromise promise) {
try {
boolean firstRegistration = neverRegistered;
// 原生ssc注册到selector未关注事件
doRegister();
neverRegistered = false;
registered = true;
// 执行NioServerSocketChannel初始化handler(不包括我们构建BootStrap注册进来的事件)
pipeline.invokeHandlerAddedIfNeeded();
safeSetSuccess(promise);
pipeline.fireChannelRegistered();
if (isActive()) {
if (firstRegistration) {
pipeline.fireChannelActive();
} else if (config().isAutoRead()) {
beginRead();
}
}
} catch (Throwable t) {
}
}
@Override
protected void doRegister() throws Exception {
boolean selected = false;
for (;;) {
try {
selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0, this);
return;
} catch (CancelledKeyException e) {
}
}
}
private void callHandlerAddedForAllHandlers() {
final PendingHandlerCallback pendingHandlerCallbackHead;
synchronized (this) {
assert !registered;
registered = true;
pendingHandlerCallbackHead = this.pendingHandlerCallbackHead;
this.pendingHandlerCallbackHead = null;
}
PendingHandlerCallback task = pendingHandlerCallbackHead; // DefaultChannelPipeline$PendingHandlerAddedTask
while (task != null) {
task.execute();
task = task.next;
}
}
3.regFuture
3.1 原生ServerSocketChannel绑定
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() {
if (regFuture.isSuccess()) {
channel.bind(localAddress, promise).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
} else {
promise.setFailure(regFuture.cause());
}
}
});
}
@Override
public ChannelFuture bind(final SocketAddress localAddress, final ChannelPromise promise) {
final AbstractChannelHandlerContext next = findContextOutbound(MASK_BIND);
EventExecutor executor = next.executor();
if (executor.inEventLoop()) {
// 启动流程已经绑定了eventLoop
next.invokeBind(localAddress, promise);
} else {
safeExecute(executor, new Runnable() {
@Override
public void run() {
next.invokeBind(localAddress, promise);
}
}, promise, null, false);
}
return promise;
}
@SuppressJava6Requirement(reason = "Usage guarded by java version check")
@Override
protected void doBind(SocketAddress localAddress) throws Exception {
// bind最终走到这里,根据java版本确认bing方法
if (PlatformDependent.javaVersion() >= 7) {
javaChannel().bind(localAddress, config.getBacklog());
} else {
javaChannel().socket().bind(localAddress, config.getBacklog());
}
}
3.2 触发NioServerSocketChannel active事件
private void invokeChannelActive() {
if (invokeHandler()) {
try {
((ChannelInboundHandler) handler()).channelActive(this);
} catch (Throwable t) {
invokeExceptionCaught(t);
}
} else {
fireChannelActive();
}
}
@Override
protected void doBeginRead() 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);
}
}