1 Channel简介
在Netty中,Channel相当于一个Socket的抽象,它为用户提供了关于Socket状态(是连接还是断开)以及对Socket的读写等操作。每当Netty建立了一个连接,都创建一个与其对应的Channel实例。
除了TCP,Netty还支持很多其他的协议,并且每种协议还有NIO和OIO(传统的阻塞IO)版本的区别。不同协议不同阻塞类型的连接都有不同的Channel类型与之对应,下表对一些常用的Channel做了简单介绍。
来看一下Channel的总体类图,如下图:
2 NioSocketChannel的创建
Bootstrap是Netty提供的一个便利的工厂类,可以通过它来完成客户端或者服务端的Netty的初始化。
首先,从客户端开始分析。
public class ChatClient {
public ChatClient connect(int port,String host,final String name){
NioEventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group)
.channel(NioSocketChannel.class)
.option(ChannelOption.SO_KEEPALIVE,true)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
System.out.println("初始化channel:" + socketChannel);
}
});
//发起同步连接操作
ChannelFuture channelFuture = bootstrap.connect(host, port).sync();
channelFuture.channel().closeFuture().sync();
}catch (InterruptedException e){
e.printStackTrace();
}finally {
//关闭,释放线程资源
group.shutdownGracefully();
}
return this;
}
public static void main(String[] args) {
new ChatClient().connect(8080,"127.0.0.1","jay");
}
}
分析如下:
1、EventLoopGroup:不论是服务端还是客户端,都必须指定EventLoopGroup。在本例中,指定了NioEventLoopGroup,表示一个NIO的EventLoopGroup。
2、ChannelType:指定Channel的类型。因为是客户端,所以使用了NioSocketChannel。
3、Handler:设置处理数据的Handler。
客户端启动Bootstrap后都做了哪些工作?看一下NioSocketChannel的类层次结构图,如下:
回到在客户端连接代码的初始化Bootstrap中,该方法调用了一个channel方法,传入的参数是NioSocketChannel.class,在这个方法中其实就是初始化了一个ReflectiveChannelFactory的对象,代码实现如下:
public B channel(Class<? extends C> channelClass) {
if (channelClass == null) {
throw new NullPointerException("channelClass");
} else {
return this.channelFactory((io.netty.channel.ChannelFactory)(new ReflectiveChannelFactory(channelClass)));
}
}
而ReflectiveChannelFactory实现了ChannelFactory接口,它提供了唯一的方法,即newChannel方法。顾名思义,ChannelFactory就是创建Channel的工厂类。进入ReflectiveChannelFactory的newChannel方法,其实现代码如下:
public T newChannel() {
try {
return (Channel)this.clazz.newInstance();
} catch (Throwable var2) {
throw new ChannelException("Unable to create Channel from class " + this.clazz, var2);
}
}
根据上面的代码,可以得出以下结论。
1、Bootstrap中的ChannelFactory实现类是ReflectiveChannelFactory。
2、通过channel方法创建的Channel具体类型是NioSocketChannel。
Channel的实例化过程其实就是调用ChannelFactory的newChannel方法,而实例化的Channel具体类型又和初始化Bootstrap时传入的channel方法的参数有关。因此对于客户端的Bootstrap而言,创建的Channel实例就是NioSocketChannel。
3 客户端Channel初始化
上面提到了如何设置一个Channel的类型,并且了解到Channel是通过ChannelFactory的newChannel方法来实例化的,那么ChannelFactory的newChannel方法在哪里调用呢?其调用链路如下图:
在AbstractBootstrap的initAndRegister方法中,调用ChannelFactory的newChannel方法来创建一个NioSocketChannel的实例,代码如下:
final ChannelFuture initAndRegister() {
Channel channel = null;
try {
channel = this.channelFactory.newChannel();
this.init(channel);
} catch (Throwable var3) {
if (channel !&#