Channel五大基本特性:
1)通道状态主要包括:打开、关闭、连接
2)通道主要的IO操作,读(read)、写(write)、连接(connect)、绑定(bind)。
3)所有的IO操作都是异步的,调用诸如read,write方法后,并不保证IO操作完成,但会返回一个凭证,在IO操作成功,取消或失败后会记录在该凭证中。
4)channel有父子关系,SocketChannel是通过ServerSocketChannel接受创建的,故SocketChannel的parent()方法返回的就是ServerSocketChannel。
5)在Channel使用完毕后,请调用close方法,释放通道占用的资源
Channel基本定义:
Channel是顶层接口,继承了AttributeMap, ChannelOutboundInvoker, ChannelPropertyAccess, Comparable,它作为一个具体IO能力的组件提供给开发者,包括read, write, connect, and bind等操作。另外还提供了Channel配置的功能,以及获取Channel所在的eventloop的功能。
channel提供给开发者:
1)获取channel当前状态(例如:是否打开,是否连接);
2)通过ChannelConfig 配置channel 的参数(例如:接收数据的缓冲区大小)
3)channel支持I/O操作(例如:read, write, connect, and bind),和通过ChannelPipeline处理当前channnel所有的I/O事件和请求。
4)所有的I/O操作都是异步的。
这意味着任何I / O调用将立即返回,不保证所要求的I/O操作有
在通话结束时已完成。相反,你将返回channelfuture 实例将通知你何时I/O请求操作已成功、失败或取消。
5)channel是分层的。
一个channel能有一个父channel,取决于它如何创建。例如。一个SocketChannel被接受连接通过ServerSocketChannel,将返回ServerSocketChannel作为父channel。通道属于层次结构的语义依赖于传输
。例如,你能写channel的实现 ,创建分channel 分享一个socket连接。作为
BEEP和SSH.
向下的访问传输的具体操作。
一些传输协议额外的操作是明确的传输。Down-cast the {@link Channel} to sub-type to invoke such operations. For example, with the old I/O datagram transport, multicast join / leave operations are provided by {@link DatagramChannel}.
6)释放资源
尽可能的调用close()或者close(ChannelPromise)对于释放所有资源,当你使用了channel。这个确保所有的资源的释放以适当的方式。
public interface Channel extends AttributeMap, ChannelOutboundInvoker, Comparable<Channel> {
/**
* 这个channel,返回全局唯一的标识符
*/
ChannelId id();
/**
* 这个Channel被注册返回EventLoop
*/
EventLoop eventLoop();
/**
* 返回这个channel的父channel
* 如果没有,返回null
*/
Channel parent();
/**
*返回这个channel的配置信息
*/
ChannelConfig config();
/**
* 返回 true,如果channel已经打开
*/
boolean isOpen();
/**
*channel是否已经注册
*/
boolean isRegistered();
/**
*Channel是否是活动或者已连接的
*/
boolean isActive();
/**
* 返回channel的ChannelMetadata,channel的自然描述
*/
ChannelMetadata metadata();
/**
channel是绑定的,返回本地地址。返回SocketAddress是应该向下更多的类型,例如InetSocketAddress对于获取详细信息。如果没有绑定,返回null
*/
SocketAddress localAddress();
/**
返回连接这个channel的远程地址。返回SocketAddress是应该向下更多的类型,例如InetSocketAddress对于获取详细信息。如果没有连接,返回null,这个channel没有连接但是能接收内容从任意的远程地址(例如DatagramChannel),use {@link DatagramPacket#recipient()} to determine the origination of the received message as this method will
return {@code null}.
*/
SocketAddress remoteAddress();
/**
当channel被关闭,将被通知返回ChannelFuture,这个方法总是返回相同的future实例。
*/
ChannelFuture closeFuture();
/**
* 当且仅当I/O线程将立即执行所请求的写操作时返回true。当此方法返回false时,任何写入请求都将排队,直到I/O线程准备处理队列写入请求。
*/
boolean isWritable();
/**
还能写入多少字节直到返回false.
这个数量总是非负的.如果isWritable()返回true,这个值就是0
*/
long bytesBeforeUnwritable();
/**
得到多少字节从底层缓冲区中排出直到返回true。
这个数量总是非负的.如果isWritable()返回true,这个值就是0
*/
long bytesBeforeWritable();
/**
返回一个局部(internal-use-only)对象,提供unsafe操作
*/
Unsafe unsafe();
/**
返回指定的ChannelPipeline.
*/
ChannelPipeline pipeline();
/**
返回指定{bytebufallocator }将用于分配{bytebuf }.
*/
ByteBufAllocator alloc();
@Override
Channel read();
@Override
Channel flush();
/**
Unsafe操作应该从不被调用在开发者代码中。这些方法仅提供实现对实际的传输,必须从I/O线程中调用,除非以下方法:
localAddress();
remoteAddress();
closeForcibly();
register(EventLoop, ChannelPromise);
deregister(ChannelPromise);
voidPromise();
*/
interface Unsafe {
/**
返回指定的{RecvByteBufAllocator.Handle},将被用于分配{ByteBuf},当接收数据时。
*/
RecvByteBufAllocator.Handle recvBufAllocHandle();
/**
返回SocketAddress对于绑定的,没有绑定返回null.
*/
SocketAddress localAddress();
/**
返回远程SocketAddress对于绑定的,没有绑定返回null.
*/
SocketAddress remoteAddress();
/**
注册{ChannelPromise}的{Channel},注册完成通知{ChannelFuture}
*/
void register(EventLoop eventLoop, ChannelPromise promise);
/**
绑定{@ SocketAddress}对于ChannelPromise}的{Channel},绑定完成通知。
*/
void bind(SocketAddress localAddress, ChannelPromise promise);
/**
连接{Channel}的{channelfuture }与给定的远程SocketAddress }。
如果一个专本地方{SocketAddress }需要作为参数。否则只是
传递{null}给它。{channelpromise }将得到通知一旦连接操作完成。
*/
void connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise);
/**
断开{Channel}的 {ChannelFuture},并且当操作完成,通知{ChannelPromise}
*/
void disconnect(ChannelPromise promise);
/**
关闭 {Channel}的{ChannelPromise},并且当操作完成,通知{ChannelPromise}
*/
void close(ChannelPromise promise);
/**
立即关闭{Channel},没有引发任何事件.当注册尝试失败时,可能是唯一有用的。
*/
void closeForcibly();
/**
注销 {Channel}的{ChannelPromise}从{EventLoop},并且当操作完成,通知{ChannelPromise}
*/
void deregister(ChannelPromise promise);
/**
一个读操作任务,在{ChannelPipeline}填满第一个{ChannelInboundHandle}读缓冲区,如果已经有一个未处理的读操作,这个方法不做任何事情。
*/
void beginRead();
/**
* 一个写操作任务
*/
void write(Object msg, ChannelPromise promise);
/**
冲洗所有写操作任务通过{#write(Object, ChannelPromise)}
*/
void flush();
/**
返回一个专门的ChannelPromise,能被重复使用和暂停操作在{Unsafe}.它永远不会被通知的成功或错误,所以只是一个占位符操作
拿{channelpromise }作为参数,但你不想得到通知。
*/
ChannelPromise voidPromise();
/**
返回{Channel}的{ChannelOutboundBuffer},等待写入请求被存储
*/
ChannelOutboundBuffer outboundBuffer();
}
}
- 从上面Netty的源码中,我们能看出channel涉及到了很多比较重要的类。像ChannelPromise ,ChannelPipeline,ChannelFuture ,EventLoop ,ByteBuff。这些类可能还会涉及到其它比较重要类,在之后详细介绍的时候再进行说明。下面制作简单的介绍。
ChannelFuture
所有的Channel操作都是异步的,Channel的返回ChannelFuture的一些操作并不阻塞,而是立即返回,在未来某个时刻我们能够获得状态来判断该操作的状态是完成还是进行还是取消。
一个channelfuture是未完成或完成。当I/O操作开始时,将创建一个新的future对象。新的future对象最初是未完成的,因为I/O操作还没有完成,它既没有成功,也没有失败,也没有被取消。如果I/O操作是成功地完成,失败或取消,future被标记为完成更具体的信息,如失败的原因。请注意,即使失败和取消属于已完成状态。
ChannelPromise
继承关系:
java.util.concurrent.Future<— Future <— ChannelFuture <— ChannelPromise
ChannelPromise继承了ChannelFuture,ChannelFuture方法主要是判断操作未来的状态,而ChannelPromise除了继承ChannelFuture的方法外,还实现了设置未来状态的写方法,
源码上写的是
Special {@link ChannelFuture} which is writable.
特殊的可写的ChannelFuture
比如ChannelFuture返回错误等情况,当我们使用ChannelPromise时,就能改变返回结果,唤醒其他操作,有点线程中条件变量的感觉。
ChannelPipeline
说到ChannelPipeline先要说责任链设计模式,简单来讲就是将一些能处理请求的对象串起来形成一条链,被处理的对象不知道被谁处理,所以在这条处理链上轮寻过,该被谁处理谁就接受此对象进行处理。
现实生活的例子,比如上级分派了一个任务做一款软件(被处理对象),放眼望去有一排攻城狮(处理请求对象),于是此任务在他们之间传递,每个攻城狮判断自己是否能做,能做就接受请求。
pipeline就是这条责任链,我们可以往上面注册,增添,删除处理事件对象,然后当待处理对象在此pipeline上传递时,哪个处理事件对象能处理则接收它。
简而言之:ChannelPipeline 是 ChannelHander 的容器,它负责 ChannelHander 的管理和事件拦截与调度。
ChannelHandler
ChannelHandler就是ChannelPipeline上面注册的处理事件对象,每个ChannelHandler接口的实现类完成一定的功能,并可以灵活的在Pipeline流水线上增加,ChannelHandler也称为事件拦截器,遇到能处理的对象事件就拦截下来处理
ChannelHandler支持注解
@Sharable是多个Pipeline共用一个ChannelHandler
@skip是跳过此ChannelHandler
ChannelHandlerAdapter
ChannelHandlerAdapter给用户提供了ChannelHandler的适配器,我们可以自定义类来继承ChannelHandlerAdapter然后根据自己需要如何处理事件对象来重新实现ChannelHandler的方法。
ChannelPipeline和ChannelHandler的详细介绍,可以看:(http://blog.csdn.net/woaixiaopangniu521/article/details/72763753)