Netty源码解析(三)bind方法(二)

编程入门 行业动态 更新时间:2024-10-24 22:30:01

Netty<a href=https://www.elefans.com/category/jswz/34/1770099.html style=源码解析(三)bind方法(二)"/>

Netty源码解析(三)bind方法(二)

上一篇说完了NioEventLoop完成的三件事,1.轮询感兴趣事件 2.处理IO事件 3.处理任务队列
流程走到了启动好reactor线程后,ServerSocketChannel注册到selector上,但是感兴趣事件填的0,我们继续跟流程,走到这里,initAndRegister方法完成,继续跟bind方法,我们看bind方法中的doBind0方法

/**** @param regFuture* @param channel  nioserversocketchannel* @param localAddress 本地地址* @param promise 标明通道是否被注册*/private static void doBind0(final ChannelFuture regFuture, final Channel channel,final SocketAddress localAddress, final ChannelPromise promise) {// 在触发channelregister()之前调用此方法。给用户处理程序设置的机会// 管道在其channelRegistered()实现中。//这里也是封装成任务,这些任务最终被事件轮询线程同步调用channel.eventLoop().execute(new Runnable() {@Overridepublic void run() {System.out.println("bind0");if (regFuture.isSuccess()) {//bind方法,添加关闭的监听事件channel.bind(localAddress, promise).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);} else {promise.setFailure(regFuture.cause());}}});}

这里也是把bind方法封装成任务,添加到任务队列中,再让executor处理任务
查看bind方法,最终会通过pipeline走到headContext,我们查看headContext的invokeBind方法

@Overridepublic void bind(ChannelHandlerContext ctx, SocketAddress localAddress, ChannelPromise promise) {unsafe.bind(localAddress, promise);}

这里有调用到了unsafe的doBind方法,

@Overridepublic final void bind(final SocketAddress localAddress, final ChannelPromise promise) {//如果没有开启reactor线程,直接抛异常assertEventLoop();if (!promise.setUncancellable() || !ensureOpen(promise)) {return;}// See:  (Boolean.TRUE.equals(config().getOption(ChannelOption.SO_BROADCAST)) &&localAddress instanceof InetSocketAddress &&!((InetSocketAddress) localAddress).getAddress().isAnyLocalAddress() &&!PlatformDependent.isWindows() && !PlatformDependent.maybeSuperUser()) {// Warn a user about the fact that a non-root user can't receive a// broadcast packet on *nix if the socket is bound on non-wildcard address.logger.warn("A non-root user can't receive a broadcast packet if the socket " +"is not bound to a wildcard address; binding to a non-wildcard " +"address (" + localAddress + ") anyway as requested.");}boolean wasActive = isActive();try {//处理bind方法doBind(localAddress);} catch (Throwable t) {safeSetFailure(promise, t);closeIfClosed();return;}/*isActive判断通道是否就绪*/if (!wasActive && isActive()) {//线程执行调用channelActive方法invokeLater(new Runnable() {@Overridepublic void run() {//这里就是用来为注册上的channel添加感兴趣事件pipeline.fireChannelActive();}});}safeSetSuccess(promise);}

里面调用了bind方法,也就是我们nio原生的绑定方法

//调用nio  api绑定ip端口@Overrideprotected void doBind(SocketAddress localAddress) throws Exception {//根据jdk版本不同进行绑定方法,到这里绑定完成if (PlatformDependent.javaVersion() >= 7) {javaChannel().bind(localAddress, config.getBacklog());} else {javaChannel().socket().bind(localAddress, config.getBacklog());}}

到这里,绑定方法就完成了,现在距离我们的serverSocketChannel的正常使用还差一步,就是为注册到selector的channel添加感兴趣事件,其实添加感兴趣事件也在unsafe的bind方法中,在完成bind方法后,会将pipeline.fireChannelActive();方法添加到任务队列中,根据handler调用链,会先调用到headContext的channelActive方法

 @Overridepublic void channelActive(ChannelHandlerContext ctx) {ctx.fireChannelActive();readIfIsAutoRead();}

我们主要研究readIfIsAutoRead方法,这里通过debug,最终会走到headContext的invokeRead方法中

@Overridepublic void read(ChannelHandlerContext ctx) {unsafe.beginRead();}

调用到unsafe的beginRead方法,最终调用到AbstaractNioChannel的doBeginRead方法

@Overrideprotected void doBeginRead() throws Exception {// Channel.read() or ChannelHandlerContext.read() was calledfinal SelectionKey selectionKey = this.selectionKey;if (!selectionKey.isValid()) {return;}readPending = true;//添加感兴趣事件final int interestOps = selectionKey.interestOps();if ((interestOps & readInterestOp) == 0) {selectionKey.interestOps(interestOps | readInterestOp);}}

还记得我们刚刚创建NioServerSocketChannel的代码吗,里面调用了
super(null, channel, SelectionKey.OP_ACCEPT);即传入了accept的感兴趣事件,在AbstaractNioChannel中保存,this.readInterestOp = readInterestOp;在这里用到。
到这里我们的NioServerSocketChannel就可以正常工作了
下一篇会讲客户端的接入流程,其实netty中代码复用非常多,理解了NioServerSocketChanel的创建和使用,再去理解NioSocketChannel就会非常简单

更多推荐

Netty源码解析(三)bind方法(二)

本文发布于:2024-03-12 22:53:23,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1732601.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:源码   方法   Netty   bind

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!