简介

channel是连接客户端和服务器端的桥梁,在netty中我们最常用的就是NIO,一般和NioEventLoopGroup配套使用的就是NioServerSocketChannel和NioSocketChannel,如果是UDP协议,那么配套使用的就是NioDatagramChannel,如果是别的协议还有其他不同的Channel类型。

这些不同channel类型有什么区别呢?一个直观的感觉就是不同的channel和channel连接使用的协议有关系,不同的channel可能适配了不同的连接协议。

事实到底是不是如此呢?在netty的内部实现中到底有多少种channel呢?今天一起来探讨一下。

ServerChannel和它的类型

虽然ServerChannel继承自Channel,但是ServerChannel本身并没有添加任何新的方法:

public interface ServerChannel extends Channel {

}

所以对ServerChannel和Channel来说都可以看做是Channel,他们只是语义上有区别。

但是因为ServerChannel继承自Channel,所以相对的ServerChannel的分类和实现要比Channel要少。所以我们先以ServerChannel为例进行讲解。

ServerChannel的实现也有很多,我们以Abstract*开头的实现为例,下面是他们的继承关系:

从上图我们可以看出,ServerChannel有六个抽象类实现,分别是AbstractEpollServerChannel,AbstractKQueueServerChannel,AbstractServerChannel,ServerSocketChannel,SctpServerChannel和ServerDomainSocketChannel。

其中前面三个抽象类同时继承自AbstractChannel。

Epoll和Kqueue

Epoll和Kqueue是两个独特的依赖于特定平台的NIO协议,其中epoll只在linux平台才支持,而kQueue则在FreeBSD、NetBSD、OpenBSD、macOS 等操作系统支持。

我们来看下AbstractEpollServerChannel的构造函数:

    protected AbstractEpollServerChannel(int fd) {
this(new LinuxSocket(fd), false);
} AbstractEpollServerChannel(LinuxSocket fd) {
this(fd, isSoErrorZero(fd));
} AbstractEpollServerChannel(LinuxSocket fd, boolean active) {
super(null, fd, active);
}

所有的构造函数都需要一个LinuxSocket的参数,LinuxSocket是一个socket用来提供对于linux native方法的访问支持。

同样的,我们再看一下AbstractKQueueServerChannel的构造函数:

    AbstractKQueueServerChannel(BsdSocket fd) {
this(fd, isSoErrorZero(fd));
} AbstractKQueueServerChannel(BsdSocket fd, boolean active) {
super(null, fd, active);
}

AbstractKQueueServerChannel的构造函数需要传入一个BsdSocket参数,BsdSocket是一个类用来提供对BSD系统的本地方法的访问。

AbstractServerChannel

AbstractServerChannel我们在之前的channel一章中已经讲过了,它的唯一实现就是LocalServerChannel,用于本地的transport。

ServerSocketChannel

ServerSocketChannel是一个以Socket连接为基础的ServerChannel,既然是Socket连接,那么ServerSocketChannel中提供了一个InetSocketAddress类型的localAddress和一个remoteAddress, 另外还有一个ServerSocketChannelConfig属性,用来存储ServerSocketChannel相关的配置信息:

public interface ServerSocketChannel extends ServerChannel {
@Override
ServerSocketChannelConfig config();
@Override
InetSocketAddress localAddress();
@Override
InetSocketAddress remoteAddress();
}

ServerDomainSocketChannel

ServerDomainSocketChannel是使用DomainSocket来进行通讯的ServerChannel。什么是DomainSocket呢?

DomainSocket的全称是unix domain socket,它又可以叫做IPC socket,也就是inter-process communication socket,是在unix平台上的同一服务器上的进程通信方式。

我们知道,协议是比较复杂的,对于传统的socket通讯来说,需要定制特定的协议,然后进行封包和解包等操作,但是使用DomainSocket,可以直接将进程的数据直接拷贝,从而节约了时间,并提高了程序的效率。

DomainSocket的地址是一个文件的路径,实际上是下面的一个结构体:

struct sockaddr_un {
sa_family_t sun_family; /* AF_UNIX ,2字节*/
char sun_path[UNIX_PATH_MAX]; /* 路径名 */
};

在ServerDomainSocketChannel中的remoteAddress和localAddress的类型都是DomainSocketAddress,DomainSocketAddress有一个socketPath属性,用来存储DomainSocket文件的路径。

SctpServerChannel

最后一个要讲解的ServerChannel是SctpServerChannel,Sctp的全称是Stream Control Transmission Protocol,他是一种类似于TCP/IP的协议。和SocketServerChannel一样,SctpServerChannel中也有一个config叫做SctpServerChannelConfig,还提供了多个bindAddress方法用来绑定InetAddress.

有关Sctp协议的具体内容,本章不深入讨论,感兴趣的朋友可以关注后续的章节。

Channel和它的类型

Channel作为ServerChannel的父类,又有哪些实现呢?

先来看下常用channel的实现类:

看起来channel的实现类非常多,基本上都是按照channel中使用传输协议的类型来的。

我们具体来看一下相应的实现类。

UnixChannel

UnixChannel表示的unix平台上的操作,它有一个fd方法,返回一个FileDescriptor:

FileDescriptor fd();

这也是unix和windows平台的区别之一,unix平台所有的一切都可以用文件来表示。

SctpChannel

在上面我讲SctpServerChannel的时候我们提过了,Sctp是一个类似于tcp/ip的协议,SctpChannel中定义了协议中需要使用到的localAddress和remoteAddress:

InetSocketAddress localAddress();

InetSocketAddress remoteAddress();

同时还定义了一些绑定方法:

    ChannelFuture bindAddress(InetAddress var1);

    ChannelFuture bindAddress(InetAddress var1, ChannelPromise var2);

    ChannelFuture unbindAddress(InetAddress var1);

    ChannelFuture unbindAddress(InetAddress var1, ChannelPromise var2);

DatagramChannel

DatagramChannel用来处理UDP协议的连接,因为UDP有广播的功能,所以DatagramChannel中提供了joinGroup的方法,来join一个multicast group:

ChannelFuture joinGroup(InetAddress multicastAddress);

当然,可以join就可以leave,还有一些leaveGroup的方法:

ChannelFuture leaveGroup(InetAddress multicastAddress);

还可以block某些地址在给定的networkInterface上的广播:

ChannelFuture block(
InetAddress multicastAddress, NetworkInterface networkInterface,
InetAddress sourceToBlock);

这些方法都和UDP的特性是息息相关的。

DomainDatagramChannel

DomainDatagramChannel和之前提到的ServerDomainSocketChannel一样,都是使用的IPC内部进程通讯技术,直接进行进程的拷贝,免去了协议解析等步骤,提升了处理速度。

DuplexChannel

DuplexChannel从名字看就是一个双向的channel,duplex Channel有一个特点,就是channel的两边可以独立的关闭,所以有下面的方法:

boolean isInputShutdown();

ChannelFuture shutdownInput();

boolean isOutputShutdown();

ChannelFuture shutdownOutput();

DuplexChannel的是实现有很多种,比如常见的NIOSocketChannel,KQueueSocketChannel,EpollSocketChannel等。

AbstractChannel

另外一个channel的非常重要的子类就是AbstractChannel,AbstractChannel有三个非常重要的实现,分别是AbstractNioChannel,AbstractKQueueChannel和AbstractEpollChannel。

这三个类使用的都是NIO技术,不同的是第一个使用的是select,后面两个使用的是平台独有的KQueue和Epoll技术。

其中NIO又可以分为NioByteChannel和NioMessageChannel,KQueue和Epoll又可以分为StreamChannel和DatagramChannel。

总结

以上就是channel在netty中的基本实现和分类。后面我们会详解讲解具体的channel到底是如何实现的。

本文已收录于 www.flydean.com

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

netty系列之:netty中各不同种类的channel详解的更多相关文章

  1. netty系列之:netty中的Channel详解

    目录 简介 Channel详解 异步IO和ChannelFuture Channel的层级结构 释放资源 事件处理 总结 简介 Channel是连接ByteBuf和Event的桥梁,netty中的Ch ...

  2. 【读后感】Netty 系列之 Netty 高性能之道 - 相比 Mina 怎样 ?

    [读后感]Netty 系列之 Netty 高性能之道 - 相比 Mina 怎样 ? 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商 ...

  3. Netty 系列之 Netty 高性能之道 高性能的三个主题 Netty使得开发者能够轻松地接受大量打开的套接字 Java 序列化

    Netty系列之Netty高性能之道 https://www.infoq.cn/article/netty-high-performance 李林锋 2014 年 5 月 29 日 话题:性能调优语言 ...

  4. SQL Server时间粒度系列----第4节季、年时间粒度详解

    本文目录列表: 1.SQL Server季时间粒度2.SQL Server年时间粒度 3.总结语 4.参考清单列表   SQL Serve季时间粒度       季时间粒度也即是季度时间粒度.一年每3 ...

  5. Python操作redis学习系列之(集合)set,redis set详解 (六)

    # -*- coding: utf-8 -*- import redis r = redis.Redis(host=") 1. Sadd 命令将一个或多个成员元素加入到集合中,已经存在于集合 ...

  6. 【HANA系列】SAP HANA XS使用服务器JavaScript Libraries详解

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA XS使用服务器 ...

  7. 【HANA系列】SAP HANA XS使用JavaScript数据交互详解

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA XS使用Jav ...

  8. PHP中的命名空间(namespace)及其使用详解

    PHP中的命名空间(namespace)及其使用详解 晶晶 2年前 (2014-01-02) 8495次浏览 PHP php自5.3.0开始,引入了一个namespace关键字以及__NAMESPAC ...

  9. Linux Shell系列教程之(八)Shell printf命令详解

    本文是Linux Shell系列教程的第(八)篇,更多shell教程请看:Linux Shell系列教程 在上一篇:Linux Shell系列教程之(七)Shell输出这篇文章中,已经对Shell p ...

随机推荐

  1. Java 书写规范简单整理

    本文带有华为Logo的PPT图片,引自:华为云课堂 目录 Java基础语句使用规范 选择结构 switch 默认要有default分支 注意break的使用 如果使用枚举,并且选项已全部列出,可以没有 ...

  2. JS介绍、意义

    HTML和CSS 京东 网页.网站和应用程序 网页:单独的一个页面 网站:一些列相关的页面组成到一起 应用程序:可以和用户产生交互,并实现某种功能. 演示JavaScript的强大 http://im ...

  3. Mac 使用自带php和Apache 安装配置Xdebug 开启本地调试模式

    Mac 安装配置php xdebug 本地调试 0.原理图 https://paper.seebug.org/308/ 测试demo构建方法 新建空白项目,目录选择Apache默认项目目录 1.下载x ...

  4. npm 查看一个包的版本信息

    有了npm 我们能够简单的一段代码就下载我们需要的包,但是包是不断更新的, 所以我们要关注包的版本信息: 现在,假设我们需要 jquery ,但是jquery现在有很多版本,我们如何通过npm查看呢? ...

  5. 关于linux shell编程,alias rm='cp $@ ~/backup; rm $@'

    书上的这个例子需要在ubuntu的低版本的系统才支持,现在基本上都不支持了,想实现也很简单自己写一个脚本先备份再删除. alias也只是做了一次替换alias rm='cp $@ ~/backup; ...

  6. 「游记」CSP-S 2021 爆零记

    推荐访问本人自建博客 \(\text{cjwen.top}\) 初赛 之前参加过「难度介于 J 组(基础组)和 S 组(提高组)之间」的 [LGR-(-13) ]SCP 2021 第一轮(初赛)模拟, ...

  7. python篇第5天【变量】

    第4天加班 多个变量赋值 Python允许你同时为多个变量赋值.例如: a = b = c = 1 以上实例,创建一个整型对象,值为1,三个变量被分配到相同的内存空间上. 您也可以为多个对象指定多个变 ...

  8. Solution -「NOI 模拟赛」彩色挂饰

    \(\mathcal{Description}\)   给定一个含 \(n\) 个点 \(m\) 条边的简单无向图,设图中最大点双的大小为 \(s\),则保证 \(s\le6\).你将要用 \(k\) ...

  9. Linux CentOS 搭建SVN并用钩子自动实现同步到Web目录

    linux安装配置SVN并设置钩子   安装说明 系统环境:CentOS-6.3安装方式:yum install (源码安装容易产生版本兼容的问题)安装软件:系统自动下载SVN软件 检查已安装版本 # ...

  10. GAN实战笔记——第三章第一个GAN模型:生成手写数字

    第一个GAN模型-生成手写数字 一.GAN的基础:对抗训练 形式上,生成器和判别器由可微函数表示如神经网络,他们都有自己的代价函数.这两个网络是利用判别器的损失记性反向传播训练.判别器努力使真实样本输 ...