千家信息网

netty ServerBootstrap.bind方法怎么使用

发表于:2025-12-01 作者:千家信息网编辑
千家信息网最后更新 2025年12月01日,本篇内容介绍了"netty ServerBootstrap.bind方法怎么使用"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大
千家信息网最后更新 2025年12月01日netty ServerBootstrap.bind方法怎么使用

本篇内容介绍了"netty ServerBootstrap.bind方法怎么使用"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

我们都知道,netty是基于java nio的,那么具体的,java nio当中的一些具体元素,比如bind,selector,channel等等具体元素,在netty当中又是如何出现的。今天我们来找一找。

首先从ServerBootstrap.bind()方法开始。

该方法的具体实现在AbstractBootstrap当中,直接看到doBind方法,

final ChannelFuture regFuture = initAndRegister();

看看 initAndRegister 这里面具体干了点什么,

首先是创建了一个channel,并且从boss group当中分配一个进程给这个新创建的channel。

Channel channel;
try {
channel = createChannel();
} catch (Throwable t) {
return VoidChannel.INSTANCE.newFailedFuture(t);
}

然后是初始化的工作,具体内容这里暂不深究。

try {
init(channel);
} catch (Throwable t) {
channel.unsafe().closeForcibly();
return channel.newFailedFuture(t);
}

然后是注册,首先得到一个promise,这个东西按照我的理解,就是为了异步的返回各种操作的执行结果,后续我们会经常见到它。然后执行register,我们又发现一个很诡异的东西unsafe,
这个东西是创建channel的时候带出来的,具体作用是跟java nio打交道,注入bind,register等操作,都在这里面完成,为什么弄这么个东西,目前不明,以后再说。

ChannelPromise regFuture = channel.newPromise();
channel.unsafe().register(regFuture);
if (regFuture.cause() != null) {
if (channel.isRegistered()) {
channel.close();
} else {
channel.unsafe().closeForcibly();
}
}

然后是AbstractChannel$AbstractUnsafe.register(),第一个判断很有意思,我们可以这样理解,如果当前channel对应的 eventLoop 已经在执行了,也就是说,当前代码已经处在了一个子线程当中,那么直接调用 register0 方法,否则,新起一个线程执行。

if (eventLoop.inEventLoop()) {
register0(promise);
} else {
try {
eventLoop.execute(new Runnable() {
@Override
public void run() {
register0(promise);
}
});
} catch (Throwable t) {
logger.warn(
"Force-closing a channel whose registration task was not accepted by an event loop: {}",
AbstractChannel.this, t);
closeForcibly();
closeFuture.setClosed();
promise.setFailure(t);
}
}

然后我们看一下 register0 里面具体干了些什么:

try {
// check if the channel is still open as it could be closed in the mean time when the register
// call was outside of the eventLoop
if (!ensureOpen(promise)) {
return;
}
doRegister();
registered = true;
promise.setSuccess();
pipeline.fireChannelRegistered();
if (isActive()) {
pipeline.fireChannelActive();
}
} catch (Throwable t) {
// Close the channel directly to avoid FD leak.
closeForcibly();
closeFuture.setClosed();
if (!promise.tryFailure(t)) {
logger.warn(
"Tried to fail the registration promise, but it is complete already. " +
"Swallowing the cause of the registration failure:", t);
}
}

首先通过promise检查了一下当前channel的状态,然后执行doRegister,这个方法在AbstractNioChannel当中实现, 主要内容如下:

selectionKey = javaChannel().register(eventLoop().selector, 0, this);

好了目前我们明确了2个问题,第一selector存在于 eventLoop 当中,具体地说,应该是在boss loop当中。第二个问题,在执行register的时候,还没有执行bind。

在之后设置了promise,并通过pipeline出发了ChannelRegistered()事件。

下面再回到 AbstractBootstrap .doBind方法,第一步,初始化和注册selector的过程都已经完成了。

final ChannelFuture regFuture = initAndRegister();
final Channel channel = regFuture.channel();
if (regFuture.cause() != null) {
return regFuture;
}

final ChannelPromise promise;
if (regFuture.isDone()) {
promise = channel.newPromise();
doBind0(regFuture, channel, localAddress, promise);
} else {
// Registration future is almost always fulfilled already, but just in case it's not.
promise = new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE);
regFuture.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
doBind0(regFuture, channel, localAddress, promise);
}
});
}

怎么理解上面那段代码,尤其是 if (regFuture.isDone()) 之后的部分,我们前面提到,具体的register过程可能是在一个子线程当中执行的,所以这里需要等待register完成,才能进行下一步bind操作。

看doBind0的实现,这里还是直接起一个线程来执行bind操作。

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());
}
}
});

看 channel.bind ,方法实现在AbstractChannel当中,很有趣,直接通过pipeline来做这个bind。那么我们来看一下pipeline.bind,实现在DefaultChannelPipeline当中,我们看到的是tail.bind,那么很显然,是要反向遍历链表,最终通过head去执行bind。那么我们看看HeadHandler.bind方法,unsafe.bind(localAddress, promise); 通过查找代码,我们发现, unsafe 就是最初我们创建的Server channel的unsafe,这是同一个东西。

我们再看一下AbstractChannel$AbstractUnsafe的bind方法,这里面涉及到一些对操作系统信息的读取和判断,然后调用了NioServerSocketChannel.doBind()方法,具体的真正的,java nio的bind操作,就在这里执行。

最后一件事,java nio当中的channel在netty当中是怎么出现的。很简单,看一下NioServerSocketChannel这个类,这个当中有一个newSocket方法,直接返回一个java 的ServerSocketChannel。

以上,我们基本达到了我们此次代码分析的目的,搞清楚了,在netty服务器启动的时候,具体干了些什么,

在netty当中找到了java nio当中的一些具体元素。

同时,我们找到了handler当中2个具体的event,bind和channelRegistered具体的发起时机。

另外,我们初步了解了netty提供的异步返回机制,ChannelFuture究竟是怎么工作的。

"netty ServerBootstrap.bind方法怎么使用"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

方法 东西 代码 内容 线程 元素 时候 过程 个子 就是 是在 更多 知识 问题 工作 实用 有趣 诡异 学有所成 接下来 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 服务器拒绝播放链请求 网络云服务器检查 网络安全防护认证考试 往u盘里拷数据库 计算机工程数据库管理系统 信管物流信息技术与软件开发 外文期刊全文数据库 网络技术服务费做什么会计科目 电脑登录服务器慢是怎么回事 广州凡科互联网科技好不好 双十一网络安全技能大赛 软件开发工程师是什么意思 国内外网络安全违法案例 我的世界斗罗大陆最强服务器 桂阳学计算机软件开发薪资 首届网络安全讲话 上海鲲鹏服务器厂家供应 如何测试服务器最大用户数 数据库为什么要建立约束 简答网络技术方法的优缺点 联想ts140服务器设置密码 魔兽卓越服务器查询 服务器无硬盘管理 代码包是放在应用服务器里面的吗 数据库软考改卷严吗 浦东新区智能化软件开发代理品牌 网络安全与监控技术 网络服务器在哪几个国家 我的世界飞行服务器 工业视觉软件开发步骤
0