一、Client
1、IoConnector:Client端的最底层接口。主要有3个方法:超时时间(ConnectTimeoutMillis),目标地址(RemoteAddress),创建连接(connect).
2、abstractIoConnector:实现了IoConnector,继承了AbstractIoService。继承了AbstractIoService同Server端一样,不再赘述。
3、abstractPollingIoConnector:
protected final ConnectFuture connect0(SocketAddress remoteAddress, SocketAddress localAddress,
IoSessionInitializer<? extends ConnectFuture> sessionInitializer) {
H handle = null;
boolean success = false;
try {
//SocketChannel sc = SocketChannel.open();
handle = newHandle(localAddress);
//返回true的条件是,对该地址进行的connect可以立即建立
if (connect(handle, remoteAddress)) {
ConnectFuture future = new DefaultConnectFuture();
//new NioSocketSession
T session = newSession(processor, handle);
initSession(session, future, sessionInitializer);
//通过IoProcessor注册和处理READ和WRITE事件,同Server端。
session.getProcessor().add(session);
success = true;
return future;
}
success = true;
} catch (Exception e) {
return DefaultConnectFuture.newFailedFuture(e);
} finally {
if (!success && handle != null) {
try {
close(handle);
} catch (Exception e) {
ExceptionMonitor.getInstance().exceptionCaught(e);
}
}
}
//创建请求,放到队列中
ConnectionRequest request = new ConnectionRequest(handle, sessionInitializer);
connectQueue.add(request);
//执行Connector内部类
startupWorker();
wakeup();
return request;
}
private class Connector implements Runnable {
public void run() {
assert (connectorRef.get() == this);
int nHandles = 0;
while (selectable) {
try {
//获取超时时间
int timeout = (int) Math.min(getConnectTimeoutMillis(), 1000L);
//selector.selector();
int selected = select(timeout);
//注册CONNECTOR事件,从队列中获取request,附着在通道上
//handle.register(selector, SelectionKey.OP_CONNECT, request);
nHandles += registerNew();
// get a chance to get out of the connector loop, if we don't have any more handles
if (nHandles == 0) {
connectorRef.set(null);
if (connectQueue.isEmpty()) {
assert (connectorRef.get() != this);
break;
}
if (!connectorRef.compareAndSet(null, this)) {
assert (connectorRef.get() != this);
break;
}
assert (connectorRef.get() == this);
}
if (selected > 0) {
//处理CONNECTOR事件,新建Session,通过IoProcessor注册和处理READ和WRITE事件,同Server端。
nHandles -= processConnections(selectedHandles());
}
processTimedOutSessions(allHandles());
nHandles -= cancelKeys();
} catch (ClosedSelectorException cse) {
// If the selector has been closed, we can exit the loop
ExceptionMonitor.getInstance().exceptionCaught(cse);
break;
} catch (Exception e) {
ExceptionMonitor.getInstance().exceptionCaught(e);
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
ExceptionMonitor.getInstance().exceptionCaught(e1);
}
}
}
if (selectable && isDisposing()) {
selectable = false;
try {
if (createdProcessor) {
processor.dispose();
}
} finally {
try {
synchronized (disposalLock) {
if (isDisposing()) {
destroy();
}
}
} catch (Exception e) {
ExceptionMonitor.getInstance().exceptionCaught(e);
} finally {
disposalFuture.setDone();
}
}
}
}
}
总结: Client端和Server端的代码结构十分类似,除了客户端对NIO的初始化不一样,建立Session以及之后对READ和WRITE事件的注册和处理都是和Server端用的相通的类核方法。二、责任链IoFilterChain1、IoFilterChain:内部类Entry是双向链表,是实现此责任链模式的基本数据结构。2、DefaultIoFilterChain
private class EntryImpl implements Entry {
//双向链表
private EntryImpl prevEntry;
private EntryImpl nextEntry;
private final String name;
//当前节点的filter
private IoFilter filter;
private final NextFilter nextFilter;
//构造方法,设置前后节点,当前节点名称,filter
private EntryImpl(EntryImpl prevEntry, EntryImpl nextEntry, String name, IoFilter filter) {
if (filter == null) {
throw new IllegalArgumentException("filter");
}
if (name == null) {
throw new IllegalArgumentException("name");
}
this.prevEntry = prevEntry;
this.nextEntry = nextEntry;
this.name = name;
this.filter = filter;
//匿名内部类创建NextFilter的实例,获取下一个Entry,调用下一个Entry的Filter,递归调用。
this.nextFilter = new NextFilter() {
public void sessionCreated(IoSession session) {
Entry nextEntry = EntryImpl.this.nextEntry;
callNextSessionCreated(nextEntry, session);
}
public void sessionOpened(IoSession session) {
Entry nextEntry = EntryImpl.this.nextEntry;
callNextSessionOpened(nextEntry, session);
}
public void sessionClosed(IoSession session) {
Entry nextEntry = EntryImpl.this.nextEntry;
callNextSessionClosed(nextEntry, session);
}
public void sessionIdle(IoSession session, IdleStatus status) {
Entry nextEntry = EntryImpl.this.nextEntry;
callNextSessionIdle(nextEntry, session, status);
}
public void exceptionCaught(IoSession session, Throwable cause) {
Entry nextEntry = EntryImpl.this.nextEntry;
callNextExceptionCaught(nextEntry, session, cause);
}
public void inputClosed(IoSession session) {
Entry nextEntry = EntryImpl.this.nextEntry;
callNextInputClosed(nextEntry, session);
}
public void messageReceived(IoSession session, Object message) {
Entry nextEntry = EntryImpl.this.nextEntry;
callNextMessageReceived(nextEntry, session, message);
}
public void messageSent(IoSession session, WriteRequest writeRequest) {
Entry nextEntry = EntryImpl.this.nextEntry;
callNextMessageSent(nextEntry, session, writeRequest);
}
public void filterWrite(IoSession session, WriteRequest writeRequest) {
Entry nextEntry = EntryImpl.this.prevEntry;
callPreviousFilterWrite(nextEntry, session, writeRequest);
}
public void filterClose(IoSession session) {
Entry nextEntry = EntryImpl.this.prevEntry;
callPreviousFilterClose(nextEntry, session);
}
public String toString() {
return EntryImpl.this.nextEntry.name;
}
};
}
}
DefaultIoFilterChain构造方法
public DefaultIoFilterChain(AbstractIoSession session) {
if (session == null) {
throw new IllegalArgumentException("session");
}
this.session = session;
//会生成头和尾2个节点,这2个节点的Filter不一样,尾节点指向头节点,非循环。
//尾节点的主要作用的,当责任链到尾部的时候,调用到自己实现的handler,从而可以获取自己需要的事件。
head = new EntryImpl(null, null, "head", new HeadFilter());
tail = new EntryImpl(head, null, "tail", new TailFilter());
//头节点指向尾节点
head.nextEntry = tail;
}