11. netty系列之:netty中SocketAddress详解
简介
Socket是一种建立客户端和服务器端连接的方式,这种方式在netty中尤其常见,在socket中客户端和服务器端需要一种机制来确定如何连接到对方,这种机制就是SocketAddress。
今天我们来详细讲解一下SocketAddress在netty中的实现。
SocketAddress
SocketAddress听名字就知道它是一个地址,事实上它是在JDK中定义的,我们来看下它的具体定义:
public abstract class SocketAddress implements java.io.Serializable {
static final long serialVersionUID = 5215720748342549866L;
}
SocketAddress在java.net包中,表示的是一个网络地址。
但是我们检查代码可以看到,SocketAddress中并没有任何内容,它的所有实现都在它的子类中,那么SocketAddress到底有那些实现类呢?
我们以一个图来观察一下,SocketAddress和它的子类实现:
可以看到,SocketAddress继承自Serializable,为什么要继承自Serializable呢?很明显SocketAddress要在网络中进行传输,所以必须要进行序列化。
SocketAddress有4个直接实现的子类分别是LocalAddress,EmbeddedSocketAddress,DomainSocketAddress,InetSocketAddress,还有两个间接实现的子类,分别是DatagramSocketAddress和DomainDatagramSocketAddress。
我们一起来看一下他们到底是什么用的。
LocalAddress
首先是LocalAddress,LocalAddress表示的是本地的数据传输地址。localAddress中有两个属性:
private final String id;
private final String strVal;
这两个属性是从netty的channel中得到的,我们看下他们的实现逻辑:
LocalAddress(Channel channel) {
StringBuilder buf = new StringBuilder(16);
buf.append("local:E");
buf.append(Long.toHexString(channel.hashCode() & 0xFFFFFFFFL | 0x100000000L));
buf.setCharAt(7, ':');
id = buf.substring(6);
strVal = buf.toString();
}
可以看出,LocalAddress的id是依赖于channel的hashCode来生成,然后进行拼接而成的,拼接后的StringBuilder中的前6个字符就是id,整个StringBuilder的值就是strVal。
而这个ID的作用就是用判断不同的LocalAddress是否相同:
public int compareTo(LocalAddress o) {
return id.compareTo(o.id);
}
可以看到因为LocalAddress并没有涉及到IP地址,所以它只能在本地使用。
EmbeddedSocketAddress
先来看下这个类的定义:
final class EmbeddedSocketAddress extends SocketAddress {
private static final long serialVersionUID = 1400788804624980619L;
@Override
public String toString() {
return "embedded";
}
}
可以看到它自定义了一个toString方法,所以这个类的用处不对,主要使用在EmbeddedChannel中,表示嵌套的channel中的地址。
因为channel是嵌套的,所以它的LOCAL_ADDRESS和REMOTE_ADDRESS实际上是不存在的。
InetSocketAddress
这个类应该是我们最常用到的socketAddress,因为它代表的是一个IP Socket Address,也就是IP address + port number, 这个IP地址也可以用hostname来替代。
InetSocketAddress中只有一个InetSocketAddressHolder类型的属性holder,而这个holder事实上是一个内部类,它定义了三个属性,分别是:
private String hostname;
private InetAddress addr;
private int port;