java channel源码_Netty 4.0 源码分析(三):Channel和ChannelPipeline

Client和server通过Channel连接,然后通过ByteBuf进行传输。每个Channel有自己的Pipeline,Pipeline上面可以添加和定义Handler和Event。

Channel类

1 package io.netty.channel;2 import io.netty.buffer.ByteBuf;

3 import io.netty.buffer.MessageBuf;

4 import io.netty.channel.socket.DatagramChannel;

5 import io.netty.channel.socket.ServerSocketChannel;

6 import io.netty.channel.socket.SocketChannel;

7 import io.netty.util.AttributeMap;

8 import java.net.InetSocketAddress;

9 import java.net.SocketAddress;

10 import java.nio.channels.SelectionKey;

11 public interface Channel extends AttributeMap, ChannelOutboundInvoker, ChannelFutureFactory, Comparable {

12     Integer id();

13     EventLoop eventLoop();

14     Channel parent();

15     ChannelConfig config();

16     ChannelPipeline pipeline();

17     boolean isOpen();

18     boolean isRegistered();

19     boolean isActive();

20     ChannelMetadata metadata();

21     ByteBuf outboundByteBuffer();

22      MessageBuf outboundMessageBuffer();

23     SocketAddress localAddress();

24     SocketAddress remoteAddress();

25     ChannelFuture closeFuture();

26     Unsafe unsafe();

27     interface Unsafe {

28         ChannelHandlerContext directOutboundContext();

29         ChannelFuture voidFuture();

30         SocketAddress localAddress();

31         SocketAddress remoteAddress();

32         void register(EventLoop eventLoop, ChannelFuture future);

33         void bind(SocketAddress localAddress, ChannelFuture future);

34         void connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelFuture future);

35         void disconnect(ChannelFuture future);

36         void close(ChannelFuture future);

37         void closeForcibly();

38         void deregister(ChannelFuture future);

39         void flush(ChannelFuture future);

40         void flushNow();

41         void suspendRead();

42         void resumeRead();

43     }

44 }

45

Channel%E7%B1%BBUML%E5%9B%BE.JPG

Channel类UML图

Netty 4.0中,定义了Channel接口,这个接口用于连接网络的socket传输,或者具有I/O操作的组件连接。这里的I/O操作有,read,write,bind,connect

Channel接口为用户提供了:

1.Channel的当前状态,比如:Channel是否open,或者Channel是否已经连接。

2.Channel的参数,比如:接受的buffer大小。

3.Channel支持的I/O操作,比如:read,write,connect,bind。

4.注册在Channel上的ChannelPipeline,ChannelPipeline用于处理所有的I/O事件和请求。

Channel类的几个重要方法

ChannelFuture closeFuture();

所有在Netty中的I/O操作都是异步的,这就意味着任何的I/O调用都会立即返回,但是无法保证所有被调用的I/O操作到最后能够成功执行完成。closeFuture() 返回一个ChannelFuture对象, 并且告诉I/O的调用者,这个I/O调用的最后状态是succeeded,failed或者canceled。

void register(EventLoop eventLoop, ChannelFuture future);

在Channel中注册EventLoop和对应的ChannelFuture。

void deregister(ChannelFuture future);

在Channel中取消ChannelFuture的注册。

在Channel的层次结构中,Channel子类的实现取决于传输的具体实现。比如SocketChannel,能够被ServerSocketChannel接受,并且SocketChannel中的getParent()方法会返回ServerSocketChannel。开发者可以实现Channel接口,共享Socket连接,比如SSH。

ChannelPipeLine接口

1 public interface ChannelPipeline extends ChannelInboundInvoker, ChannelOutboundInvoker {

2     MessageBuf inboundMessageBuffer();

3     ByteBuf inboundByteBuffer();

4     MessageBuf outboundMessageBuffer();

5     ByteBuf outboundByteBuffer();

6     ChannelPipeline addFirst(String name, ChannelHandler handler);

7     ChannelPipeline addFirst(EventExecutorGroup group, String name, ChannelHandler handler);

8     ChannelPipeline addLast(String name, ChannelHandler handler);

9     ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler);

10     ChannelPipeline addBefore(String baseName, String name, ChannelHandler handler);

11     ChannelPipeline addBefore(EventExecutorGroup group, String baseName, String name, ChannelHandler handler);

12     ChannelPipeline addAfter(String baseName, String name, ChannelHandler handler);

13     ChannelPipeline addAfter(EventExecutorGroup group, String baseName, String name, ChannelHandler handler);

14     ChannelPipeline addFirst(ChannelHandler

9b8a8a44dd1c74ae49c20a7cd451974e.png handlers);

15     ChannelPipeline addFirst(EventExecutorGroup group, ChannelHandler

9b8a8a44dd1c74ae49c20a7cd451974e.png handlers);

16     ChannelPipeline addLast(ChannelHandler

9b8a8a44dd1c74ae49c20a7cd451974e.png handlers);

17     ChannelPipeline addLast(EventExecutorGroup group, ChannelHandler

9b8a8a44dd1c74ae49c20a7cd451974e.png handlers);

18     void remove(ChannelHandler handler);

19     ChannelHandler remove(String name);

20      T remove(Class handlerType);

21     ChannelHandler removeFirst();

22     ChannelHandler removeLast();

23     void replace(ChannelHandler oldHandler, String newName, ChannelHandler newHandler);

24     ChannelHandler replace(String oldName, String newName, ChannelHandler newHandler);

25      T replace(Class oldHandlerType, String newName, ChannelHandler newHandler);

26     ChannelHandler first();

27     ChannelHandlerContext firstContext();

28     ChannelHandler last();

29     ChannelHandlerContext lastContext();

30     ChannelHandler get(String name);

31      T get(Class handlerType);

32     ChannelHandlerContext context(ChannelHandler handler);

33     ChannelHandlerContext context(String name);

34     ChannelHandlerContext context(Class extends ChannelHandler> handlerType);

35     Channel channel();

36     List names();

37     Map toMap();

38 }

ChannelPipeline%E7%B1%BBUML%E5%9B%BE.JPG

ChannelPipeline类UML图

ChannelHandler接口用于处理和拦截Channel接口中的ChannelEvents。Netty中的ChannelPipeline概念使用了Intecepting Filter Patter模式来实现,这样做的好处是允许用户可以完全控制Event的处理,并且控制ChannelHandlers在ChannelPipeline的交互。

当一个全新的Channel创建的时候,都必须创建一个ChannelPipeline,并使Channel和ChannelPipeline想关联。这种关联关系式永久性的,这意味着,一旦一个ChannelPipeleine和Channel关联了,那么这个Channel就在也无法关联其他ChannelPipeline,也无法取消与当前ChannelPipeline的关联。

【官方推荐】使用Channel接口中的pipeleine()方法来创建一个ChannelPipelien,而不要用new去实例一个ChannePipeline类

ChannelPipeline pipeline = Channel.pipeline();

Pipeline中的事件流

ChannelPipeline%E4%B8%AD%E7%9A%84%E4%BA%8B%E4%BB%B6%E6%B5%81.JPG

ChannelPipeline中的事件流

图中显示了一个典型的ChannelHandler或者ChannelPipeline对于ChannelEvent的处理流程。ChannelHandler接口有两个子类,分别是ChannelUpstreamHandler(ChannelInboundHandler)和ChannelDownstreamHandler(ChannelOutBoundstreamHandler)。这两个之类用于处理每一个ChannelEvent,然后由ChannelHandlerContext.sendUpstream(ChannelEvent)和ChannelHandlerContext.sendDownstream(ChannelEvent)将每一个ChannelEvent转发到最近的handler。根据upstream和downstream的不同,每个Event的处理也会有所不同。

如事件流图中的左边显示,Upstream Handlers会从低至上的处理一个Upstream Event。Inbound的数据有图中底部的Netty Internal I/O threads生成。通过调用InputStream.readByte(byte[])方法,可以从一个远程的服务器读取inbound data。如果一个upstream event达到upstream handler的顶部,那么这个upstream event最终将被丢弃掉。

如事件流图中的右边显示,Dpstream Handlers会从低至上的处理一个Upstream Event。Downstream Handler会生成和传输outbount数据流,比如一个写操作。当一个Downstream Event达到Downstream Handler的底部,那么与之相关的Channal中的I/O thread对对其进行处理。Channel中的I/Othread会执行真正的操作,例如OutputStream.write(byte[])。

假设我们创建了这么一个ChannelPipeline,

ChannelPipelien p = Channel.pipeline();

p.addLast(“1”, new UpstreamHandlerA());

p.addList(“2”, new UpstreamHandlerB());

p.addList(“3”, new DownstreamHandlerA());

p.addList(“4”, new DownstreamHandlerB());

p.addList(“5”, new UpstreamHandlerX());

在ChannelPipeline的栈中,upstream的执行顺序是1,2,而downstream的执行顺序是4,3。

生产Pipeline

在一条Pipeline中,一般会有一个或者多个ChannelHandler用于接收I/O事件(read)或者请求I/O操作(write,close)。一个典型的服务器会有如下的一个ChannelPipeline用于处理不同的ChannelHandler。

ChannelPipelien p = Channel.pipeline();

p.addLast(“decoder”, new MyProtocalDecoder());

p.addList(“encoder”, new MyProtocalEncoder());

p.addList(“executor”, new ExectionHandler());

p.addList(“handler”, new MyBusinessLogicHandler());

1.Protocal Decoder –将二进制数据(如ByteBuf)装换成Java对象。

2.Protocal Encoder –将Java对象装换成二进制数据。

3.ExecutionHandler –使用一个线程模型。

4.BusinessLogicHandler –执行一个具体的业务逻辑(如数据库访问)

由于ChannelPipeline是线程安全的,所以ChannelHandler可以再任何时候从ChannelPipeline中被添加或者删除。例如,可以插入一个Handler用于处理被加密过的敏感数据信息,在处理之后,删除掉这个Handler。

备注:因为笔者开始写Netty源码分析的时候,Netty 4.0还是处于Alpha阶段,之后的API可能还会有改动,笔者将会及时更改。使用开源已经有好几年的时间了,一直没有时间和精力来具体研究某个开源项目的具体实现,这次是第一次写开源项目的源码分析,如果文中有错误的地方,欢迎读者可以留言指出。对于转载的读者,请注明文章的出处。

希望和广大的开发者/开源爱好者进行交流,欢迎大家的留言和讨论。

-----------------------------------------------------

Silence, the way to avoid many problems;

Smile, the way to solve many problems;

posted on 2012-11-25 14:53 Chan Chen 阅读(8944) 评论(0)  编辑  收藏 所属分类: Netty

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/523493.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一拍即合、一见钟情之后,智慧城市的“福利”来啦……

戳蓝字“CSDN云计算”关注我们哦!“未来双方的合作会针对智慧城市、智慧建筑以及智慧地域开发等领域开展创新型的解决方案,这种创造对于目前已经存在的,该领域技术甚至是竞争对手都是一个强大的震撼与颠覆。”达索系统董事会副主席兼首席执行…

Springboot部署到Tomcat,可以不带项目名进行访问

文章目录1. 进入tomcat的conf目录2. 编辑server.xml2.1. 修改第一处2.2. 修改第二处2.3. 发布war包2.4. 浏览器请求2.5. windows样例1. 进入tomcat的conf目录 cd /app/tomcat8081/conf/2. 编辑server.xml Tomcat9使用war包设置默认项目需要设置下server.xml就行 vim server.…

python ndarray append_9-Python-NumPy数组元素的添加与删除

数组元素的添加与删除 相关函数列表如下:函数元素及描述resize返回指定形状的新数组append将值添加到数组末尾insert沿指定轴将值插入到指定下标之前delete删掉某个轴的子数组,并返回删除后的新数组unique查找数组内的唯一元素1)返回指定大小的新数组num…

Java -jar 如何在后台运行项目

演示项目: GitHub链接:https://github.com/gb-heima/java-jar-nohup zip下载链接:https://github.com/gb-heima/java-jar-nohup/archive/master.zip git下载地址: git clone gitgithub.com:gb-heima/java-jar-nohup.git编译打包 …

裁员1700人,IBM 声称内部调整团队;谷歌将以26亿美元全现金收购Looker,绝对大手笔...

关注并标星星CSDN云计算极客头条:速递、最新、绝对有料。这里有企业新动、这里有业界要闻,打起十二分精神,紧跟fashion你可以的!每周三次,打卡即read更快、更全了解泛云圈精彩newsgo go go 贝索斯旗下蓝色起源将登月球…

修改Tomcat默认的端口

文章目录1. 进入/app/tomcat8081/conf,编辑server.xml文件2. 修改3个端口2.1. 第一个:停止端口,默认8005,修改为80062.2. 第二个:修改http访问端口,默认8080修改为80812.3. 第三个:修改APJ端口&…

Lambda 表达式有何用处?

戳蓝字“CSDN云计算”关注我们哦!我们知道,对于一个Java变量,我们可以赋给其一个“值”。如果你想把“一块代码”赋给一个Java变量,应该怎么做呢?比如,我想把右边那块代码,赋给一个叫做aBlockOf…

Java Web项目_order下载、运行

项目简介: order为GitHub开源项目,作为java web测试的参考项目,可以快速编译打包运行,UI设计采用bootstrap页面美观! 文章目录一、 order项目下载1.1. 项目链接:1.2. zip包下载链接:1.3. GitHub…

纯粹,极致!他用两个词阐释了UCloud

“我觉得有一个词是肯定的:纯粹,另一个词可能是极致。但这个词我有些犹豫,因为我们做的还不够好。”UCloud技术副总裁杨镭在UCloud用户大会期间接受老孙独家采访时这样形容UCloud。 UCloud技术副总裁杨镭关于UCloud:一家简单、纯粹…

java gc堆中的分区_jvm内存各个区域详解

内存区域划分Java虚拟机所管理的内存区域分为如下部分:方法区、GC堆、虚拟机栈、本地方法栈、PC程序计数器。其中方法区、GC堆是所有线程共享的;虚拟机栈、本地方法栈、PC程序计数器是各个线程独占的。image.pngPC程序计数器程序计数器可以看做是当前线程…

157 亿美元 !Salesforce 收购 Tableau !微软发布警告,表明黑客利用Office漏洞发动垃圾邮件攻击……...

关注并标星星CSDN云计算极客头条:速递、最新、绝对有料。这里有企业新动、这里有业界要闻,打起十二分精神,紧跟fashion你可以的!每周三次,打卡即read更快、更全了解泛云圈精彩newsgo go go 荣耀在成都的全球首家Life概…

Git 远程配置_03

文章目录1. 生成SSH key 认证证书2. 查看公钥3. 拷贝公钥的内容,并设置到github中远程配置就是怎样和远程仓库建立连接? 1. 在本地生成公钥和私钥(认证证书) 2. 把本地生成的公钥复制到远程仓库的ssh key中保存1. 生成SSH key 认证证书 ssh-keygen -t rsa -C &qu…

Jenkins修改管理员密码

Jenkins的加密方式 Jenkins 的密码采用的是Java加解密工具 jBCrypt,我也是第一次接触到这种加密方式,实在被他惊叹到了!这种加密方式每次加密同一个明文竟然都是得到不一样的结果,那他又是通过怎样的方式来解密的呢?原…

Storm精华问答 | 如何理解spout/bolt的生命周期?

戳蓝字“CSDN云计算”关注我们哦!Storm是Twitter开源的分布式实时大数据处理框架,被业界称为实时版Hadoop。随着越来越多的场景对Hadoop的MapReduce高延迟无法容忍,比如网站统计、推荐系统、预警系统、金融系统等, 大数据实时处理…

刚刚!6月榜单:JS跌惨,Python又霸榜,C++再无翻身可能!

Python勇者无敌!最近一份PYPL 6月报告了来了,通过半年的发展,Python基本已奠定2019年-2020的地位,持续称王就对了!PLPY 6月榜单,JS跌惨只见Python笑,哪闻C哭PYPL 发布 6 月编程语言指数榜啦。毫…

java vector 输出_5.7(java学习笔记)Vector、Enumeration

一.VectorVector类实现一个可扩展的数组对象。与数组一样,它包含可以使用整数索引访问。它的基本操作方法add(int index, E element),get(int index),indexOf(Object o)等操作方法与数组中的方法类似这里就不叙述了。我们主要看一个方法&…

企业实战案例01_Jenkins_连接远程执行shell脚本

文章目录一、Jenkins 远程连接执行shell脚本1.1. 新建节点1.2. 配置节点信息二、连接远程验证测试2.1. 创建任务2.2. 添加注释2.3. 设置最大构建数量2.4. 限制项目的运行节点2.5. 选择构建环境2.6. 填写获取Tomact目录列表脚本2.7. 立即构建项目2.8. 查看控制台日志监控一、Jen…

纯粹,极致!他用两个词阐释了UCloud | 人物志

戳蓝字“CSDN云计算”关注我们哦!“我觉得有一个词是肯定的:纯粹,另一个词可能是极致。但这个词我有些犹豫,因为我们做的还不够好。”UCloud技术副总裁杨镭在UCloud用户大会期间接受老孙独家采访时这样形容UCloud。UCloud技术副总…

企业实战案例02_Jenkins_连接远程GitLab拉取代码

编译、打包 文章目录一、任务新建和配置信息1. 新建任务2. 添加描述3. 设置构建的最大数量4. 添加Git构建参数5.复制远程项目链接地址6. 粘贴远程项目地址7. 添加凭据7. 要编译的分支8. 效果图9. 编译和打包项目二、构建项目和日志监听1. 查看工作区(构建项目前&…

java责任链模式审批请假_Java使用责任链模式处理学生请假问题详解

本文实例讲述了Java使用责任链模式处理学生请假问题。分享给大家供大家参考,具体如下:一. 模式定义在责任链模式中,很多对象由每一个对象对其下家的引用而连接起来,形成一条链。客户端应用请求在这个链上进行传递,直到…