文章目录
Channel接口
- Channel在Netty中描述成一个网络插座,具备连接,绑定,读写等功能,下面部分是Netty源码中Channel接口的注释。
+ 并且所有的IO操作都是异步的,操作都会立即返回,通过Netty的Future接口(可能是不通的子类,比如ChannelFuture)来获取结果,
+ Channel是具备等级的,一个Channel可以有一个parent,这取决于这个Channel是如何创建的,比如说,当ServerSocketChannel通
过accept()方法接受一个SocketChannel时,那么SocketChannel的父亲是ServerSocketChannel,调用SocketChannel的parent()方法
返回该ServerSocketChannel对象。
+ 可以使用向下转型访问特点的传输方法,某些子类Channel会提供一些所需的特定操作,可以向下转型到这样的子类,从而获得特定
操作。比如说,对于UDP的数据报的传输,有特定的join()和leave()操作,我们可以向下转型到DatagramChannel从而使用这些操作。
+ 当Channel不使用是,通过close方法释放资源
一、ChannelOutboundInvoker
- ChannelOutboundInvoker是Channel的父接口,定义了相关的基本操作,部分方法如下:
public interface ChannelOutboundInvoker {
/**
* 绑定到指定地址,完成后会通知ChannelFuture,不管成功或者失败
*/
ChannelFuture bind(SocketAddress localAddress);
/**
* 连接到指定地址,操作完成后通知ChannelFuture,不管成功或者失败
*/
ChannelFuture connect(SocketAddress remoteAddress);
/**
* 请求断开连接,操作完成后通知ChannelFuture,不管成功或者失败
*/
ChannelFuture disconnect();
/**
* 关闭Channel,完成后通知ChannelFuture,不管成功或者失败
*/
ChannelFuture close();
/**
* 将Channel从EventExecutor注销,完成后会通知ChannelFuture,,不管成功或者失败
*/
ChannelFuture deregister();
/**
* 断开连接
*/
ChannelFuture disconnect(ChannelPromise promise);
/**
* 关闭
*/
ChannelFuture close(ChannelPromise promise);
/**
* 注销
*/
ChannelFuture deregister(ChannelPromise promise);
/**
* 从Channel读数据到入站buffer,如果读到数据就触发一次channelRead事件,如果可以继续读取数据会触发channelReadComplete事件
*/
ChannelOutboundInvoker read();
/**
* 请求通过ChannelPipeline写数据 不会触发flush
*/
ChannelFuture write(Object msg);
/**
* 返回成功的ChannelFuture
*/
ChannelFuture newSucceededFuture();
/**
* 返回失败的ChannelFuture
*/
ChannelFuture newFailedFuture(Throwable cause);
}
二、Channel
2.1 接口方法
- 下面是Channel接口里面的方法
public interface Channel extends AttributeMap, ChannelOutboundInvoker, Comparable<Channel> {
/**
* 返回Channel的编号id
*/
ChannelId id();
/**
* 返回Channel注册到的EventLoop对象
*/
EventLoop eventLoop();
/**
* 返回父Channel对象
*/
Channel parent();
/**
* 返回Channel配置参数
*/
ChannelConfig config();
/**
* 判断Channel是否打开。
*/
boolean isOpen();
/**
* 判断Channel是否注册
*/
boolean isRegistered();
/**
* 判断Channel是否激活
* 对于服务端 ServerSocketChannel ,true 表示 Channel 已经绑定到端口上,可提供服务
* 对于客户端 SocketChannel ,true 表示 Channel 连接到远程服务器
*/
boolean isActive();
/**
* 返回Channel的元数据,元数据描述了Channel
*/
ChannelMetadata metadata();
/**
* 返回Channel绑定的本地地址
*/
SocketAddress localAddress();
/**
* 返回Channel连接的远端地址
*/
SocketAddress remoteAddress();
/**
* Channel关闭时会调用的Future对象,总是会返回一个对象
*/
ChannelFuture closeFuture();
/**
* Channel 是否可写
* 当 Channel 的写缓存区 outbound 非 null 且可写时,返回 true
*/
boolean isWritable();
/**
* 获得距离不可写还有多少字节数,总会返回一个正数,如果不可写了就会返回0
*/
long bytesBeforeUnwritable();
/**
* 获得距离可写还要多少字节数,总会返回一个正数,如果可写了就会返回0
*/
long bytesBeforeWritable();
/**
* Unsafe 对象
*/
Unsafe unsafe();
/**
* 返回Channel对应所属的ChannelPipeline对象,用于处理 Inbound 和 Outbound 事件的处理
*/
ChannelPipeline pipeline();
/**
* ByteBuf分配器
*/
ByteBufAllocator alloc();
@Override
Channel read();
@Override
Channel flush();
}
将方法稍微整理一下看的更清楚些:
方法分类 | 方法 |
---|---|
状态判断 | isOpen、isRegistered、isActive、isWritable |
属性获取 | id、eventLoop、parent、config、、metadata、localAddress、remoteAddress、unsafe、pipeline、alloc、voidPromise |
结果获取 | closeFuture、newPromise、newSucceededFuture、newFailedFuture |
IO相关 | bind、connect、disconnect、close、deregister、read、write、flush、writeAndFlush |
2.2 Unsafe接口
- 在Unsafe接口中有部分和ChannelOutboundInvoker接口一样的方法,比如register、bind、flush、read、write等。实际上Unsafe作为Channel的内部类,负责处理底层NIO相关的I/O事件,Channel则使用责任链的方式通过ChannelPipeline将事件提供给用户自定义处理。
- Unsafe直译是不安全,其实这个不安全是指程序员一般不要直接使用它,它通常是程序所使用的接口方法的内部或者底层实现。
interface Unsafe {
/**
* ByteBuf 分配器的处理器
*/
RecvByteBufAllocator.Handle recvBufAllocHandle();
/**
* 本地地址
*/
SocketAddress localAddress();
/**
* 远端地址
*/
SocketAddress remoteAddress();
/**
* 注册,注册成功后会通知ChannelPromise的
*/
void register(EventLoop eventLoop, ChannelPromise promise);
/**
* 绑定到本地地址,并且绑定成后通知ChannelPromise
*/
void bind(SocketAddress localAddress, ChannelPromise promise);
/**
* 连接远程地址,从ChannelPromise获取结果
*/
void connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise);
/**
* 断开连接,成功断开后会通知ChannelPromise
*/
void disconnect(ChannelPromise promise);
/**
* 关闭连接,成功后会通知ChannelPromise
*/
void close(ChannelPromise promise);
/**
* 立刻断开Channel,不触发任何时间,可能在注册失败的时候有用
*/
void closeForcibly();
/**
* 将Channel从EventLoop注销,成功完成后通知ChannelPromise
*/
void deregister(ChannelPromise promise);
/**
* 当ChannelPipeline中第一个ChannelInboundHandler的buffer被填满的时候,执行一个读操作,如果已经有读操作了就不做任何事情
*/
void beginRead();
/**
* Schedules a write operation. 执行一个写操作
*/
void write(Object msg, ChannelPromise promise);
/**
* flush所有的write操作
*/
void flush();
ChannelPromise voidPromise();
ChannelOutboundBuffer outboundBuffer();
}
三、Channel子接口
- Channel接口是非常抽象的,而且根据不同的底层操作系统平台,在实现上可能又会有差异,因此其对应的继承关系非常复杂,从继承图中可以看到,在Netty中其子接口非常多,实现类也会有很多,这里我们先看看其子接口,下一篇文章再看实现类。
3.1 AbstractChannel
- Channel接口的骨架实现
3.2 DuplexChannel
- DuplexChannel代表双边通信Channel,两个方向通信可以独立关闭
3.3 UnixChannel
- UnixChannel是暴露给类Unix系统去实现的api
3.4 ServerChannel
- ServerChannel没有定义任何的接口方法,只是一个标记接口,ServerChannel可以接受连接并创建子Channel来接受连接,ServerSocketChannel是最好的例子
3.5 SctpChannel
- SctpChannel是一种面向消息的连接传输,支持多流和多宿主。有NioSctpChannel和OioSctpChannel两个实现类
3.6 DatagramChannel
- DatagramChannel代表UDP的Channel通道
3.7 Http2StreamChannel
-
Http2StreamChannel使用很少,实现类也很少,
-
后续的文章中,我们按照子接口的分类来阅读源码,比如我们可以从DuplexChannel的SocketChannel来看看它有哪些子类,SocketChannel代表客户端的Channle通道,后面会看到SocketChannel有NioSocketChannel、OioSocketChannel、EpollSocketChannel和KQueueSocketChannel这几个实现类,并且这四个实现类都继承了骨架抽象类AbstractChannel,这种设计非常经典,接口一层一层继承,然后衍生出不同类型的子接口,通过模板模式先实现骨架,子类继承骨架抽象类然重写实现自己的特殊方法。另外一个很重要的接口就是ServerChannel,它标记了服务端的Channel通道,后续我们都慢慢分析。
-
下面补充一张SocketChannel的继承图,可以看出四个子类实现了SocketChannel接口,并且都继承了AbstractChannel。