Netty源码分析接口系列2.1 Channel接口

###################################################################################
后续文章中都会对一些代码逻辑进行说明,但原文的英文注释一般不会直译,进行保留,只会说明那些没有注释的地方
###################################################################################

本文中关联的所有文章的总目录可以参看:系列文章目录

1. 前言

      了解socket编码的都知道socekt的三个重要接口Byte,Channel,Selector.而Netty框架也是缺少不了这些东西,只不过是对这些东西进行了重写,但要实现的功能都是一样的;

1.1 jdk中的Channel讲解

      对于jdk中的Channel接口,里面的方法很少,只有两个
isOpen() 告诉调用者这个通道是否打开,如果打开反就true,否则返回false

close() 关闭这个通道。
1)在通道关闭后如果有调用I/O操作的,那么就会报 _ClosedChannelException_异常;
2)如果这个通道已经关闭了,再重复调用close方法不会产生任何效果;
3)这个方法可以在任何时候调用;如果有某个线程已经调用这个close方法,那么其它的线程来调用时将会阻塞,直到第一个线程调用完成,然后这些线程执行是不会产生任何效果的;

jdk中的Channel接口的具体描述如下所示:

      通道可以表示诸如硬件设备,文件,网络套接字或程序组件之类的实体的开放连接,该实体能够执行一个或多个不同的I / O操作(例如,读取或写入)。
      通道只能是打开或者关闭的。 通道在创建时即打开,一旦关闭,便保持关闭状态。 通道关闭后,任何在其上调用I / O操作的尝试都将引发ClosedChannelException。 可以通过调用isOpen方法来测试通道是否打开。
      通道通常旨在对多线程访问安全,对接口规范以及扩展和实现此接口的类中所述。

2. Netty的Channel接口

      现在我们回归正题,我们现在是要熟悉Netty的Channel接口,看看这个接口到底是做了哪些东西?

2.1 Channel 接口的描述

它是网络套接字或能够进行I / O操作(例如读取,写入,连接和绑定)的组件的钮带


通道为用户提供的功能有:

  1. 通道的当前状态(例如:是否打开?是否已连接?)
  2. 通道的配置参数(例如接收缓冲区大小),
  3. 通道支持的I / O操作(例如,读取,写入,连接和绑定),
  4. 以及ChannelPipeline,处理所有与通道关联的I / O事件和请求。

所有的I/O操作都是异步的
      Netty中的所有I / O操作都是异步的。这意味着任何I / O调用都将立即返回,而不能保证在调用结束时已经完成了请求的I / O操作。相反,将返回一个带有ChannelFuture类的实例,该实例将在请求的I / O操作成功,失败或取消时通知您。


渠道是层级的
       渠道可以有一个父项,具体取决于其创建方式。例如,ServerSocketChannel接受的SocketChannel将返回ServerSocketChannel作为其parent()的父级。
       层次结构的语义取决于Channel所属的传输实现。例如,您可以编写一个新的Channel实现,以创建共享一个套接字连接的子通道,就像BEEP和SSH一样。


一些特定的传输的操作需要其子类实现
       一些传输会公开特定于该传输的其他操作。将Channel向下转换为子类型以调用此类操作。例如,对于旧的I / O数据报传输,DatagramChannel提供了多播连接/离开操作。


释放资源
       一旦完成Channel,调用close()或close(ChannelPromise)释放所有资源很重要。这样可以确保所有的资源以适当的方式释放,例如:filehandles。

2.2 Channel 接口中的方法

2.2.1 id()

这个接口如下所示:

//返回一个全局唯一Channel的标识
ChannelId id();

在Netty中,实现ChannelId的方法有很四个:
CustomChannelId:这个是自定义的渠道id生成,由用户自己实现
DefaultChannelId: 这个是默认的渠道id生成,里面生成id用的是雪花算法。感兴趣的朋友可以看下
EmbeddedChannelId:虚拟的id生成器,里面hashCode,toString方法的值都是固定的。
Http2StreamChannelId:这个主要是用于http协议的。相比较其它的而言,里面会多一个parentId;

2.2.2 eventLoop()

这个接口如下所示:

// 返回注册Channel的EventLoop对象
EventLoop eventLoop();

EventLoop对象的作用是:一但Channel注册成功后,它将处理这个通道所有的I/O操作。一般一个EventLoop的实现类能够处理多个Channel。该接口的具体的功能会在一个单独的篇章中进行讲解;

2.2.3 parent()

// 如果该渠道没有父渠道,那么这个方法就会返回null
Channel parent();

2.2.4 config()

// 返回这个渠道的具体配置信息
ChannelConfig config();

ChannelConfig接口说明

      它是Channel配置属性的集合
      对于设置特殊的属性,我们需要使用其特定实现的子类的配置类型来处理。比如SocketChannelConfig 类我们可以如下设置:

Channel ch = ...;
 SocketChannelConfig cfg = (SocketChannelConfig) ch.getConfig();
 cfg.setTcpNoDelay(false);

选项map集合
      选项映射属性是动态只写属性,它允许Channel配置的ChannelConfig不用转换成真正的子类而进行设置。 要更新选项集合,请调用setOptions(Map)这个方法。

所有ChannelConfig具有以下选项:

名称关联的设置方法
ChannelOption.CONNECT_TIMEOUT_MILLISChannelConfig.setConnectTimeoutMillis(int)
ChannelOption.WRITE_SPIN_COUNTChannelConfig.setWriteSpinCount(int)
ChannelOption.WRITE_BUFFER_WATER_MARKChannelConfig.setWriteBufferWaterMark(WriteBufferWaterMark)
ChannelOption.ALLOCATORChannelConfig.setAllocator(ByteBufAllocator)
ChannelOption.AUTO_READChannelConfig.setAutoRead(boolean)
      ChannelConfig的子类型中提供更多选项。 例如,您可以配置SocketChannelConfig这个类中特定于TCP / IP socket的参数;

2.2.5 isOpen()

// 通道如果已经打开并且在后续会可以被激活,就返回true.
boolean isOpen();

2.2.6 isRegistered()

// 如果Channel已向EventLoop注册,则返回true。
boolean isRegistered();

2.2.7 isActive()

// 如果通道处于活动状态且已连接,则返回true。
boolean isActive();

2.2.8 localAddress()

// 返回此通道绑定到的本地地址。 应该将返回的SocketAddress转换为更具体的类型(例如InetSocketAddress)以检索详细信息。
// 返回:此通道的本地地址。 如果未绑定此通道,则为null。
SocketAddress localAddress();

2.2.9 remoteAddress()

// 返回此通道连接到的远程地址。 因此,应该将SocketAddress转换为更具体的类型(例如InetSocketAddress)以检索详细信息。
// 返回:此通道的远程地址。 如果未连接此通道,则为null。如果未连接此通道,因为此方法将返回null,但它可以从任意远程地址接收消息(例如DatagramChannel,请使用DatagramPacket.recipient()确定接收到的消息的来源。
SocketAddress remoteAddress();

2.2.10 closeFuture()

// 当这个通道关闭时,会返回ChannelFuture。 这个方法会一直返回同一个ChannelFuture实例
ChannelFuture closeFuture();

2.2.11 isWritable()

// 当且仅当I / O线程将立即执行所要求的写操作时,才返回true。 
// 当此方法返回false时发出的所有写请求都将排队,直到I/O线程准备好处理排队的写请求为止。
boolean isWritable();

2.2.12 bytesBeforeUnwritable()

// 获取直到isWritable()返回false之前可以写入的字节数。此数量始终为非负数。 如果isWritable()为false,则为0。
long bytesBeforeUnwritable();

2.2.13 bytesBeforeWritable()

// 直到isWritable()返回true之前,必须从底层缓冲区中耗尽多少字节。此数量始终为非负数。 如果isWritable()为true,则为0。
long bytesBeforeWritable();

2.2.14 unsafe()

// 返回一个Unsafe 操作对象仅供内部使用
Unsafe unsafe();

Unsafe 这个类不应该被用户编写的代码来调用。它仅提供以下方法来进行实际的传输,并且必须从I/O线程中调用;这些方法包含:
•localAddress()
•remoteAddress()
•closeForcibly()
•register(EventLoop, ChannelPromise)
•deregister(ChannelPromise)
•voidPromise()

2.2.15 pipeline()

// 返回分配的ChannelPipeline
ChannelPipeline pipeline();

2.2.16 alloc()

// 返回分配的ByteBufAllocator,它将用于分配ByteBufs。
ByteBufAllocator alloc();

2.2.17 read()

//请求将数据从Channel读取到第一个入站缓冲区,如果已读取数据,则触发
// ChannelInboundHandler.channelRead(ChannelHandlerContext,Object)事件,
// 并触发channelReadComplete事件,以便处理程序可以决定继续读取。 如果已经有一个待处理的读取操作,则此方法不执行任何操作。

//这个方法会导致调用Channel的ChannelPipeline中包含的下一个ChannelOutboundHandler的ChannelOutboundHandler.read(ChannelHandlerContext)方法。
@Override
Channel read();

对于读写一个重要的ChannelPipeline这个接口,我们会在单独的篇章中再详细讲解

2.2.18 flush()

// 通过此ChannelOutboundInvoker请求刷新所有缓冲的消息。
@Override
Channel flush();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值