Netty 学习(八):新连接接入源码说明

作者: Grey

原文地址:

博客园:Netty 学习(八):新连接接入源码说明

CSDN:Netty 学习(八):新连接接入源码说明

新连接的接入分为3个过程

  1. 检测到有新连接。

  2. 将新连接注册到 worker 线程。

  3. 注册新连接的读事件。

检测新连接的代码在NioEventLoop中的processSelectedKey()方法中

    private void processSelectedKey(SelectionKey k, AbstractNioChannel ch) {
......
final AbstractNioChannel.NioUnsafe unsafe = ch.unsafe();
......
// Also check for readOps of 0 to workaround possible JDK bug which may otherwise lead
// to a spin loop
if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) {
unsafe.read();
}
.....
}

启动一个 Netty 服务端和 Netty 客户端,在unsafe.read()这一行打断点,可以得到这里的unsafe就是NioMessageUnsafe,进入NioMessageUnsaferead()方法,

这个方法主要做的事情就是:创建,设置并绑定NioSocketChannel

     private final List<Object> readBuf = new ArrayList<Object>();

        @Override
public void read() {
......
do {
// 创建`NioSocketChannel`
int localRead = doReadMessages(readBuf);
......
} while (continueReading(allocHandle));
......
// 设置并绑定 NioSocketChannel
int size = readBuf.size();
for (int i = 0; i < size; i ++) {
readPending = false;
pipeline.fireChannelRead(readBuf.get(i));
}
readBuf.clear();
allocHandle.readComplete();
pipeline.fireChannelReadComplete(); ......
}
}

创建NioSocketChannel调用的是doReadMessages()方法,通过Debug,可以看到doReadMessage()来自于NioServerSocketChannel

    @Override
protected int doReadMessages(List<Object> buf) throws Exception {
SocketChannel ch = SocketUtils.accept(javaChannel()); try {
if (ch != null) {
buf.add(new NioSocketChannel(this, ch));
return 1;
}
} catch (Throwable t) {
logger.warn("Failed to create a new channel from an accepted socket.", t); try {
ch.close();
} catch (Throwable t2) {
logger.warn("Failed to close a socket.", t2);
}
} return 0;
}

可以看到此时调用的是 Java 底层的accept()方法,创建了一条 JDK 层面的Channel, Netty 将其封装成自定义的NioSocketChannel,并加入一个List

继续 Debug,进入 NioSocketChannel 的构造方法中,调用的是AbstractNioByteChannel的构造方法

    protected AbstractNioByteChannel(Channel parent, SelectableChannel ch) {
super(parent, ch, SelectionKey.OP_READ);
}

这个方法类似在 NIO 编程中,注册 OP_READ 事件,表示 Channel 对读事件感兴趣。

接下来是设置并绑定NioSocketChannel,处理每个NioSocketChannel,通过 Debug 可以来到AbstractUnsaferegister0()方法

private void register0(ChannelPromise promise) {
// 注册Selector
doRegister();
// 执行 handler
pipeline.invokeHandlerAddedIfNeeded(); // 传播 ChannelRegistered事件
pipeline.fireChannelRegistered(); // 注册读事件
if (isActive()) {
if (firstRegistration) {
pipeline.fireChannelActive();
} else if (config().isAutoRead()) {
// This channel was registered before and autoRead() is set. This means we need to begin read
// again so that we process inbound data.
//
// See https://github.com/netty/netty/issues/4805
beginRead();
}
}
}

这个方法主要完成的事情就是:

  1. NioSocketChannel注册到Selector

  2. 配置自定义的Handler

  3. 将连接注册事件传播下去,调用了每个HandlerchannelRegistered方法。

  4. 注册读事件。

完整代码见:hello-netty

本文所有图例见:processon: Netty学习笔记

更多内容见:Netty专栏

参考资料

跟闪电侠学 Netty:Netty 即时聊天实战与底层原理

深度解析Netty源码

Netty 学习(八):新连接接入源码说明的更多相关文章

  1. Netty是如何处理新连接接入事件的?

    更多技术分享可关注我 前言 前面的分析从Netty服务端启动过程入手,一路走到了Netty的心脏——NioEventLoop,又总结了Netty的异步API和设计原理,现在回到Netty服务端本身,看 ...

  2. Netty-新连接接入源码解读

    本片博文来看Netty的服务端是如何处理新连接接入问题的 什么是新连接接入?以及新连接接入前,Netty处于什么状态 netty的服务端NioServerSocketChannel初始化,注册在Bos ...

  3. Netty学习(三)高性能之ByteBuf源码解析

    原文链接: https://juejin.im/post/5db8ea506fb9a02061399ab3 Netty 的 ByteBuf 类型 Pooled(池化).Unpooled(非池化) Di ...

  4. Netty服务端NioEventLoop启动及新连接接入处理

    一 Netty服务端NioEventLoop的启动 Netty服务端创建.初始化完成后,再向Selector上注册时,会将服务端Channel与NioEventLoop绑定,绑定之后,一方面会将服务端 ...

  5. 很值得学习的java 画图板源码

    很值得学习的java 画图板源码下载地址:http://download.csdn.net/source/2371150 package minidrawpad; import java.awt.*; ...

  6. Spring学习之——手写Spring源码V2.0(实现IOC、D、MVC、AOP)

    前言 在上一篇<Spring学习之——手写Spring源码(V1.0)>中,我实现了一个Mini版本的Spring框架,在这几天,博主又看了不少关于Spring源码解析的视频,受益匪浅,也 ...

  7. iOS学习——布局利器Masonry框架源码深度剖析

    iOS开发过程中很大一部分内容就是界面布局和跳转,iOS的布局方式也经历了 显式坐标定位方式 --> autoresizingMask --> iOS 6.0推出的自动布局(Auto La ...

  8. 【Orleans开胃菜系列2】连接Connect源码简易分析

    [Orleans开胃菜系列2]连接Connect源码简易分析 /** * prism.js Github theme based on GitHub's theme. * @author Sam Cl ...

  9. Netty 服务端:新连接接入

    本文主要分析服务端新连接的接入过程,主要分为以下 3 各步骤: select 操作: processSelectedKeys 操作. 1. select 操作 在分析 select 操作前,先要回顾一 ...

随机推荐

  1. 算法竞赛进阶指南——0x15 字符串学习笔记

    K M P模式匹配 #include <bits/stdc++.h> using namespace std; #define N 100 char s[N]; char m[N]; in ...

  2. python中的标识符和保留字

    保留字,有一些单词被赋予了特定的意义,这些单词不能作为对象的名字 想要快速获取python中的关键字可以通过以下的程 序来快速实现 import keyword print(keyword.kwlis ...

  3. 第十九天python3 json和messagepack

    json的数据类型官网:https://www.json.org/ 值: 双引号内的字符串,数值,true和false,null,对象,数组:字符串: 双引号内的任意字符的组合,可以有专一字符:数值: ...

  4. python shutil相关操作

    python shutil模块常用操作 高级的 文件.文件夹.压缩包 处理模块 1.将文件内容拷贝至另一个文件中 shutil.copyfileobj(src, dist, length=16*102 ...

  5. 从零开始实现lmax-Disruptor队列(六)Disruptor 解决伪共享、消费者优雅停止实现原理解析

    MyDisruptor V6版本介绍 在v5版本的MyDisruptor实现DSL风格的API后.按照计划,v6版本的MyDisruptor作为最后一个版本,需要对MyDisruptor进行最终的一些 ...

  6. 安卓手机如何无线连接adb?

    一般情况,大家adb调试手机,都是通过数据线的,但这样又是不太方便,所以我们可以通过WLAN来adb. 我的是华为手机,进入:设置-关于手机,连续点击版本号,唤出开发者模式.然后去返回设置-系统和更新 ...

  7. MySQL sql优化(摘抄自文档)

    前言 有人反馈之前几篇文章过于理论缺少实际操作细节,这篇文章就多一些可操作性的内容吧. 注:这篇文章是以 MySQL 为背景,很多内容同时适用于其他关系型数据库,需要有一些索引知识为基础. 优化目标 ...

  8. 停止、启动nginx以及在windows下使用dos命令停止占用的端口

    windows下使用dos命令查看占用端口号并停止 windows+R打开命令窗口 查找占用端口对应的PID(进程号) netstat -ano|findstr "port" # ...

  9. 学习与尝试 --> 事件风暴

    事件风暴 1. 基础概念 术语 执行者 -----> 是指执行的角色,系统的主体,是导致系统状态变化的触发源 人员,系统的用户,操作人员等 系统,系统本身执行的,或者调度的,自动触发的 ,第三方 ...

  10. Reactive UI -- 反应式编程UI框架入门学习(二)

    前文Reactive UI -- 反应式编程UI框架入门学习(一)  介绍了反应式编程的概念和跨平台ReactiveUI框架的简单应用. 本文通过一个简单的小应用更进一步学习ReactiveUI框架的 ...