Netty源码解读-server端(一)
创始人
2024-05-25 20:32:13
0

一、回顾NIO中的server

下面是我在学习nio时,写的selctor版本的服务端,具体代码如下:

public static void nioSelectorServer() throws Exception{//1。创建SelectorSelector selector = Selector.open();ServerSocketChannel ssc = ServerSocketChannel.open();ssc.configureBlocking(false);//默认是true,设置为false就是非阻塞模式(下面的accept方法就会变成非阻塞)//2。建立selector 和 channel 的联系(注册)//SelectionKey 就是将来事件发生后,通过它可以知道事件和哪个channel的事件SelectionKey ssckey = ssc.register(selector, 0, null);// key 只关注 accept 事件ssckey.interestOps(SelectionKey.OP_ACCEPT);log.info("register key:{}",ssckey);ssc.bind(new InetSocketAddress(8080));while (true) {//3.select当啊,没有事件发生,线程阻塞。有事件发生,线程才会恢复运行//在事件未处理时,select不会阻塞。( 处理有两种方法:key.cancel() 和 key.chaneel().accept()  )selector.select();//4.处理事件,selectedKeys 内部包含了所有发生的事件Iterator iter = selector.selectedKeys().iterator();while (iter.hasNext()) {SelectionKey key = iter.next();//!!!处理key时,要从selectedKey集合中删除,否则下厨处理可能抛出空指针(至于为什么可以看image/1.png)iter.remove();log.info("key: {}",key);//5.区分事件类型if (key.isAcceptable()) {//如果下面三行取消,whilet(true)代码块就会一直运行,打印上面的logServerSocketChannel channel = (ServerSocketChannel)key.channel();SocketChannel sc = channel.accept();//处理事件sc.configureBlocking(false);SelectionKey scKey = sc.register(selector, 0, null);scKey.interestOps(SelectionKey.OP_READ);log.info("{}",sc);}else if (key.isReadable()) {try {SocketChannel channel = (SocketChannel) key.channel();//拿到触发事件的channelByteBuffer buffer = ByteBuffer.allocate(16);int read = channel.read(buffer);//如果是正常断开,read方法返回值是-1if (read == -1){key.cancel();//!!!!}else {buffer.flip();System.out.println(Charset.defaultCharset().decode(buffer));}}catch (IOException e) {e.printStackTrace();//!!!因为客户端断开了,因此需要将key取消(从selector 的 keys 集合中真正删除key)key.cancel();}}}}}

从上述代码中,我们可以看到几个重要的步骤:
在这里插入图片描述

二、Bind源码分析

1.大体观摩

下面是我编写的netty版本server端的demo
在这里插入图片描述
咱可以重点看一下doBind方法中调用的下面这两个方法,注意线程是怎么从main线程变成Nio线程的
在这里插入图片描述

2.initAndRegister方法

2.1 initAndRegister方法可以大体上看成下面两个部分,上面是init,下面是register
在这里插入图片描述

2.2 init相关步骤

2.2.1往下追channelFactory.newChannel()的底层,发现是init其实就是通过反射的方式调用构造方法:
在这里插入图片描述
2.2.2上面这个初始化的方法其实会调用到NioServerSocketChannel的构造方法中去,下面是其构造方法的部分源码:
从中可以得知nio原生的ServerSocketChannel.open操作是在此执行的。
在这里插入图片描述

在这里插入图片描述

2.2.3回到initAndRegister方法,咱们在看看其调用的init()做了什么事情?
答:主要就是给NioServerSocketChanel添加了一个handler处理器
在这里插入图片描述

小结:init相关操作主要做了两件事:
1.创建出了NioServerSocketChannel对象,ServerSocketChannel.open()
2.为NioServerSocketChannel对象添加了一个handler处理器,等待后续调用执行






2.3 register相关步骤

2.3.1回到initAndRegister方法,咱继续看 config().group().register(channel); 方法的底层,需要追很深哦
可以发现在这里面发生了线程的切换,注意切换为Nio线程执行时,main线程会继续往下执行,这里先提一嘴留个影响。

在这里插入图片描述
2.3.2继续追register0,首先看其内部调用的doRegister
从中可以得知nio原生的ServerSocketChannel的register方法在此执行
在这里插入图片描述
2.3.3继续看register0中调用的 pipeline.invokeHandlerAddedIfNeeded() 的源码
这个方法其实就是执行了2.2.3步骤中添加的handler,为ServerSocketChannel添加acceptHandler,当accept事件发生后建立链接
在这里插入图片描述

2.3.4继续看register0中调用的 safeSetSuccess(promise)
这个方法的作用是给promise对象赋值,好让doBind方法中的main线程继续执行后续逻辑
在这里插入图片描述
小结:register相关操作主要做了3件事:
1.将serverSocketChannel绑定到了Selector上
2.执行了前面init方法中准备好的handler,目的是给NioServerSocketChannel添加一个关注accept事件的handler
3.当前面两部都完成后,让dobind方法中的main线程继续执行doBind0

3.doBind0方法

上面2.3.4可以得知执行到这一步时NioServerSocket以及绑定了一个Accept事件
dobind0其底层调用到了AbstractChannel中的bind方法
在这里插入图片描述

3.1dobind方法底层

底层相当于就是执行nio原生的ServerSocketChannel的bind方法
在这里插入图片描述

3.2invokeLater方法底层

它会去执行每个handler的active方法,重点是看head头节点的active
在这里插入图片描述
从其底层可以看出是调用到了nio的原生方法selectionKey.interestOps,让selector关注到accept事件
在这里插入图片描述
小结:dobind0主要做了2件事:
1.执行ServerSocketChannel的bind方法,绑定端口号
2.执行selectionKey.interestOps,关注Accept事件

相关内容

热门资讯

【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
AsusVivobook无法开... 首先,我们可以尝试重置BIOS(Basic Input/Output System)来解决这个问题。...
ASM贪吃蛇游戏-解决错误的问... 要解决ASM贪吃蛇游戏中的错误问题,你可以按照以下步骤进行:首先,确定错误的具体表现和问题所在。在贪...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...