目录
Channel详解
Channel代表网络socket或能够进行IO操作的组件的连接关系。这些IO操作包括读、写、连接和绑定。Netty中的Channel提供了如下功能:
- 查询当前Channel的状态。例如,是打开还是已连接状态等。
- 提供Channel的参数配置。如接收缓冲区大小。
- 提供支持的IO操作。如读、写连接和绑定
- 提供ChannelPipeline。ChannelPipelin用于处理所有与Channel关联的IO事件和请求。
Channel的特点
1. 所有IO操作都是异步的
IO调用将立即返回,返回一个ChannelFuture实例。
2. Channel是分层的
3. 向下转型以下访问特定于传输的操作
4. 释放资源
Channel接口方法
public interface Channel extends AttributeMap, ChannelOutboundInvoker, Comparable<Channel> {
ChannelId id();
EventLoop eventLoop();
Channel parent();
ChannelConfig config();
boolean isOpen();
boolean isRegistered();
boolean isActive();
ChannelMetadata metadata();
SocketAddress localAddress();
SocketAddress remoteAddress();
ChannelFuture closeFuture();
boolean isWritable();
long bytesBeforeUnwritable();
long bytesBeforeWritable();
Channel.Unsafe unsafe();
ChannelPipeline pipeline();
ByteBufAllocator alloc();
Channel read();
Channel flush();
public interface Unsafe {
Handle recvBufAllocHandle();
SocketAddress localAddress();
SocketAddress remoteAddress();
void register(EventLoop var1, ChannelPromise var2);
void bind(SocketAddress var1, ChannelPromise var2);
void connect(SocketAddress var1, SocketAddress var2, ChannelPromise var3);
void disconnect(ChannelPromise var1);
void close(ChannelPromise var1);
void closeForcibly();
void deregister(ChannelPromise var1);
void beginRead();
void write(Object var1, ChannelPromise var2);
void flush();
ChannelPromise voidPromise();
ChannelOutboundBuffer outboundBuffer();
}
}
- id()方法返回全局唯一的ChannelId
- eventLoop()方法返回分配给该Channel的EventLoop,一个EventLoop就是一个线程,用来处理连接的生命周期中所发生的事件
- parent()方法返回该Channel的父Channel
- config()方法返回该Channel的ChannelConfig,其中包含了该Channel的所有配置设置支持热更新
- pipeline()方法返回该Channel对应的ChannelPipeline
- alloc方法返回分配给该Channel的ByteBufAllocator,可以用来分配ByteBuf
ChannelOutboundInvoker接口
声明了所有出站的网络操作:
package io.netty.channel;
import java.net.SocketAddress;
public interface ChannelOutboundInvoker {
ChannelFuture bind(SocketAddress var1);
ChannelFuture connect(SocketAddress var1);
ChannelFuture connect(SocketAddress var1, SocketAddress var2);
ChannelFuture disconnect();
ChannelFuture close();
ChannelFuture deregister();
ChannelFuture bind(SocketAddress var1, ChannelPromise var2);
ChannelFuture connect(SocketAddress var1, ChannelPromise var2);
ChannelFuture connect(SocketAddress var1, SocketAddress var2, ChannelPromise var3);
ChannelFuture disconnect(ChannelPromise var1);
ChannelFuture close(ChannelPromise var1);
ChannelFuture deregister(ChannelPromise var1);
ChannelOutboundInvoker read();
ChannelFuture write(Object var1);
ChannelFuture write(Object var1, ChannelPromise var2);
ChannelOutboundInvoker flush();
ChannelFuture writeAndFlush(Object var1, ChannelPromise var2);
ChannelFuture writeAndFlush(Object var1);
ChannelPromise newPromise();
ChannelProgressivePromise newProgressivePromise();
ChannelFuture newSucceededFuture();
ChannelFuture newFailedFuture(Throwable var1);
ChannelPromise voidPromise();
}
ChannelFuture用于获取异步的结果,ChannelPromise是对ChannelFuture的扩展,支持写的操作。ChannelPromise也被称为可写的ChannelFuture。
AttributeMap接口
package io.netty.util;
public interface AttributeMap {
<T> Attribute<T> attr(AttributeKey<T> var1);
<T> boolean hasAttr(AttributeKey<T> var1);
}
AttributeMap就是类似于Map的键值对,键就是AttributeKey类型,值是Attribute类型。
Netty提供了AttributeMap的默认实现类DefaultAttributeMap,与JDK中的ConcurrentHashMap相比,在高并发下DefaultAttributeMap可以更加节省内存。
package io.netty.util;
import io.netty.util.internal.ObjectUtil;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
/**
* Default {@link AttributeMap} implementation which not exibit any blocking behaviour on attribute lookup while using a
* copy-on-write approach on the modify path.<br> Attributes lookup and remove exibit {@code O(logn)} time worst-case
* complexity, hence {@code attribute::set(null)} is to be preferred to {@code remove}.
*/
public class DefaultAttributeMap implements AttributeMap {
private static final AtomicReferenceFieldUpdater<DefaultAttributeMap, DefaultAttribute[]> ATTRIBUTES_UPDATER =
AtomicReferenceFieldUpdater.newUpdater(DefaultAttributeMap.class, DefaultAttribute[].class, "attributes");
private static final DefaultAttribute[] EMPTY_ATTRIBUTES = new DefaultAttribute[0];
/**
* Similarly to {@code Arrays::binarySearch} it perform a binary search optimized for this use case, in order to
* save polymorphic calls (on comparator side) and unnecessary class checks.
*/
private static int searchAttributeByKey(DefaultAttribute[] sortedAttributes, AttributeKey<?> key) {
int low = 0;
int high = sortedAttributes.length - 1;
while (low <= high) {
int mid = low + high >>> 1;
DefaultAttribute midVal = sortedAttributes[mid];
AttributeKey midValKey = midVal.key;
if (midValKey == key) {
return mid;
}
int midValKeyId = midValKey.id();
int keyId = key.id();
assert midValKeyId != keyId;
boolean searchRight = midValKeyId < keyId;
if (searchRight) {
low = mid + 1;
} else {
high = mid - 1;
}
}
return -(low + 1);
}
private static void orderedCopyOnInsert(DefaultAttribute[] sortedSrc, int srcLength, DefaultAttribute[] copy,
DefaultAttribute toInsert) {
// let's walk backward, because as a rule of thumb, toInsert.key.id() tends to be higher for new keys
final int id = toInsert.key.id();
int i;
for (i = srcLength - 1; i >= 0; i--) {
DefaultAttribute attribute = sortedSrc[i];
assert attribute.key.id() != id;
if (attribute.key.id() < id) {
break;
}
copy[i + 1] = sortedSrc[i];
}
copy[i + 1] = toInsert;
fi