8. netty系列之:channel,ServerChannel和netty中的实现
简介
我们知道channel是netty中用于沟通ByteBuf和Event的桥梁,在netty服务的创建过程中,不管是客户端的Bootstrap还是服务器端的ServerBootstrap,都需要调用channel方法来指定对应的channel类型。
那么netty中channel到底有哪些类型呢?他们具体是如何工作的呢?一起来看看。
channel和ServerChannel
Channel在netty中是一个interface,在Channel中定义了很多非常有用的方法。通常来说如果是客户端的话,对应的channel就是普通的channel。如果是服务器端的话,对应的channel就应该是ServerChannel。
那么客户端channel和服务器端channel有什么区别呢?我们先来看下ServerChannel的定义:
public interface ServerChannel extends Channel {
// This is a tag interface.
}
可以看到ServerChannel继承自Channel,表示服务端的Channel也是Channel的一种。
但是很奇怪的是,你可以看到ServerChannel中并没有新增任何新的方法。也就是说ServerChannel和Channel在定义上本质是一样的。你可以把ServerChannel看做是一个tag interface而已。
那么channel和ServerChannel有什么联系呢?
我们知道在Channel中定义了一个parent方法:
Channel parent();
这个parent方法返回的是该channel的父channel。我们以最简单的LocalChannel和LocalServerChannel为例,来查看一下他们的父子关系到底是怎么创建的。
首先parent的值是通过LocalChannel和LocalServerChannel的公共父类AbstractChannel来实现的:
protected AbstractChannel(Channel parent) {
this.parent = parent;
id = newId();
unsafe = newUnsafe();
pipeline = newChannelPipeline();
}
对于LocalChannel来说,可以通过它的构造函数来设置parent channel:
protected LocalChannel(LocalServerChannel parent, LocalChannel peer) {
super(parent);
config().setAllocator(new PreferHeapByteBufAllocator(config.getAllocator()));
this.peer = peer;
localAddress = parent.localAddress();
remoteAddress = peer.localAddress();
}
我们知道当client端想要连接到server端的时候,需要调用client channel的connect方法,对于LocalChannel来说,它的connect方法实际上调用的是pipeline的connect方法:
public ChannelFuture connect(SocketAddress remoteAddress) {
return pipeline.connect(remoteAddress);
}
最终会调用LocalChannel中的LocalUnsafe.connect方法。
而在LocalUnsafe.connect方法中又会调用serverChannel.serve方法。
serverChannel的newLocalChannel方法会创建新的LocalChannel并返回:
protected LocalChannel newLocalChannel(LocalChannel peer) {
return new LocalChannel(this, peer);
}
这里使用newLocalChannel方法创建的LocalChannel就是serverChannel的子channel。
最后返回的LocalChannel会作为client端LocalChannel的peer channel而存在。
netty中channel的实现
在netty中channel和Serverchannel有很多个实现类,用来完成不同的业务功能。
为了循序渐进一步步了解netty中channel的秘密,这里我们先来探讨一下netty中channel的基本实现LocalChannel和LocalServerChannel的工作原理。
下图是LocalChannel和LocalServerChannel的主要继承和依赖关系:
从图中可以看到,LocalChannel继承自AbstractChannel而LocalServerChannel则继承自AbstractServerChannel。