一、NioSocketConnector发起连接后,在其父类AbstractPollingIoConnector的多线程内部类Connector中,会监听通道上的OP_CONNECT事件:int selected=select(timeOut);服务端完成连接后,这里往下执行
if (selected > 0) {
nHandles -= processConnections(selectedHandles());
}
processConnections处理事件。
private int processConnections(Iterator<H> handlers) {
int nHandles = 0;
// Loop on each connection request
while (handlers.hasNext()) {
H handle = handlers.next();
handlers.remove();
ConnectionRequest connectionRequest = getConnectionRequest(handle);
if (connectionRequest == null) {
continue;
}
boolean success = false;
try {
if (finishConnect(handle)) {
T session = newSession(processor, handle);
initSession(session, connectionRequest, connectionRequest.getSessionInitializer());
// Forward the remaining process to the IoProcessor.
session.getProcessor().add(session);
nHandles++;
}
success = true;
} catch (Throwable e) {
connectionRequest.setException(e);
} finally {
if (!success) {
// The connection failed, we have to cancel it.
cancelQueue.offer(connectionRequest);
}
}
}
return nHandles;
}
1、finishConnect(handle)在NioSocketConnector
protected boolean finishConnect(SocketChannel handle) throws Exception {
if (handle.finishConnect()) {
SelectionKey key = handle.keyFor(selector);
if (key != null) {
key.cancel();
}
return true;
}
return false;
}
SocketChannel.finishConnect()阻塞着完成channel的连接。接下来初始化session的内容和服务端初始化Session是一样的。
2、T session = newSession(processor, handle);封装一个NioSocketSession
3、initSession(session, future, sessionInitializer);设置session的参数
4、session.getProcessor().add(session);AbstractPollingIoProcessor内部类Processor.run()。
private int handleNewSessions() {
int addedSessions = 0;
for (S session = newSessions.poll(); session != null; session = newSessions.poll()) {
if (addNow(session)) {
// A new session has been created
addedSessions++;
}
}
return addedSessions;
}
AbstractPollingIoProcessor.addNow():
private boolean addNow(S session) {
boolean registered = false;
try {
init(session);
registered = true;
// Build the filter chain of this session.
IoFilterChainBuilder chainBuilder = session.getService().getFilterChainBuilder();
chainBuilder.buildFilterChain(session.getFilterChain());
// DefaultIoFilterChain.CONNECT_FUTURE is cleared inside here
// in AbstractIoFilterChain.fireSessionOpened().
// Propagate the SESSION_CREATED event up to the chain
IoServiceListenerSupport listeners = ((AbstractIoService) session.getService()).getListeners();
listeners.fireSessionCreated(session);
} catch (Throwable e) {
ExceptionMonitor.getInstance().exceptionCaught(e);
try {
destroy(session);
} catch (Exception e1) {
ExceptionMonitor.getInstance().exceptionCaught(e1);
} finally {
registered = false;
}
}
return registered;
}
listeners.fireSessionCreated(session);IoServiceListenerSupport类
public void fireSessionCreated(IoSession session) {
boolean firstSession = false;
if (session.getService() instanceof IoConnector) {
synchronized (managedSessions) {
firstSession = managedSessions.isEmpty();
}
}
// If already registered, ignore.
if (managedSessions.putIfAbsent(session.getId(), session) != null) {
return;
}
// If the first connector session, fire a virtual service activation event.
if (firstSession) {
fireServiceActivated();
}
// Fire session events.
IoFilterChain filterChain = session.getFilterChain();
filterChain.fireSessionCreated();
filterChain.fireSessionOpened();
int managedSessionCount = managedSessions.size();
if (managedSessionCount > largestManagedSessionCount) {
largestManagedSessionCount = managedSessionCount;
}
cumulativeManagedSessionCount++;
// Fire listener events.
for (IoServiceListener l : listeners) {
try {
l.sessionCreated(session);
} catch (Throwable e) {
ExceptionMonitor.getInstance().exceptionCaught(e);
}
}
}
filterChain.fireSessionCreated();DefaultIoFilterChain类
public void fireSessionCreated() {
Entry head = this.head;
callNextSessionCreated(head, session);
}
DefaultIoFilterChain.callNextSessionCreated():遍历过滤器链的sessionCreated方法
private void callNextSessionCreated(Entry entry, IoSession session) {
try {
IoFilter filter = entry.getFilter();
NextFilter nextFilter = entry.getNextFilter();
filter.sessionCreated(nextFilter, session);
} catch (Throwable e) {
fireExceptionCaught(e);
}
}
最终会执行到内置末位过滤器TailFilter.sessionCreated():
public void sessionCreated(NextFilter nextFilter, IoSession session) throws Exception {
try {
session.getHandler().sessionCreated(session);
} finally {
// Notify the related future.
ConnectFuture future = (ConnectFuture) session.removeAttribute(SESSION_CREATED_FUTURE);
if (future != null) {
future.setSession(session);
}
}
}
session.getHandler().sessionCreated(session);此方法是调用业务类handler.sessionCreated方法,一些初始化的内容可以再此方法中实现。
future.setSession(session);DefaultConnectFuture类:
public void setSession(IoSession session) {
if (session == null) {
throw new IllegalArgumentException("session");
}
setValue(session);
}
setValue():
public void setValue(Object newValue) {
synchronized (lock) {
// Allow only once.
if (ready) {
return;
}
result = newValue;
ready = true;
if (waiters > 0) {
lock.notifyAll();
}
}
notifyListeners();
}
将ready值设为true。这个值与接下来的一步有关。
二、future.awaitUninterruptibly();这使程序阻塞等待连接的建立后再执行之后的的session = future.getSession();
从上一步可以知道,客户端发起connect后需要等服务端响应请求已建立了,才会接着初始化session等,
而在channel上等待OP_CONNECT事件是在AbstractPollingIoConnector类的多线程内部类Connector中执行。
意味着Connector在监听,例子中的代码还并发着往下执行。所以就用这个方法将业务代码兜住。
直到连接建立,session初始化完成,用于判断是否完成的开关就是上一步的DefaultConnectFuture
父类DefaultIoFuture.ready的这个字段。
future.awaitUninterruptibly();DefaultConnectFuture类
public IoFuture awaitUninterruptibly() {
try {
await0(Long.MAX_VALUE, false);
} catch (InterruptedException ie) {
// Do nothing : this catch is just mandatory by contract
}
return this;
}
await0()
private boolean await0(long timeoutMillis, boolean interruptable) throws InterruptedException {
long endTime = System.currentTimeMillis() + timeoutMillis;
if (endTime < 0) {
endTime = Long.MAX_VALUE;
}
synchronized (lock) {
if (ready) {
return ready;
} else if (timeoutMillis <= 0) {
return ready;
}
waiters++;
try {
for (;;) {
try {
long timeOut = Math.min(timeoutMillis, DEAD_LOCK_CHECK_INTERVAL);
lock.wait(timeOut);
} catch (InterruptedException e) {
if (interruptable) {
throw e;
}
}
if (ready) {
return true;
}
if (endTime < System.currentTimeMillis()) {
return ready;
}
}
} finally {
waiters--;
if (!ready) {
checkDeadLock();
}
}
}
}
synchronized (lock)和wait()方法配合同步修改ready的开关。这个lock就是DefaultIoFuture对象,在其初始化是设值的。
public DefaultIoFuture(IoSession session) {
this.session = session;
this.lock = this;
}
lock.wait(timeOut);方法是这个线程wait一段时间,并暂时释放lock对象即DefaultIoFuture对象。
让DefaultConnectFuture.setValue()方法,在session初始化完成后被调用时,有机会对ready开关进行同步修改,将其标记为true。使得await0()下次再判断ready时即可返回,让业务接着执行future.getSession()。
客户端和服务端建立连接的过程何其相似。服务端启动后绑定OP_ACCEPT,监听客户端建立连接的请求。
客户端发送建立连接的请求后绑定OP_CONNECT,监听服务端完成建立连接的请求。
而双方在收到消息后都会交由NioProcessor建立session,绑定OP_READ,并监听通道上对方传过来的数据。