服务端建立请求后,就阻塞在NioProcessor父类AbstractPollingIoProcessor的内部类Processor.run()中的int selected = select(SELECT_TIMEOUT);等待OP_READ事件。
当客户端往通道中写数据后,就唤醒往下执行。
if (selected > 0) {
//LOG.debug("Processing ..."); // This log hurts one of the MDCFilter test...
process();
}
process()
private void process() throws Exception {
for (Iterator<S> i = selectedSessions(); i.hasNext();) {
S session = i.next();
process(session);
i.remove();
}
}
process(session);
private void process(S session) {
// Process Reads
if (isReadable(session) && !session.isReadSuspended()) {
read(session);
}
// Process writes
if (isWritable(session) && !session.isWriteSuspended()) {
// add the session to the queue, if it's not already there
if (session.setScheduledForFlush(true)) {
flushingSessions.add(session);
}
}
}
read()
private void read(S session) {
IoSessionConfig config = session.getConfig();
int bufferSize = config.getReadBufferSize();
IoBuffer buf = IoBuffer.allocate(bufferSize);
final boolean hasFragmentation = session.getTransportMetadata().hasFragmentation();
try {
int readBytes = 0;
int ret;
try {
if (hasFragmentation) {
while ((ret = read(session, buf)) > 0) {
readBytes += ret;
if (!buf.hasRemaining()) {
break;
}
}
} else {
ret = read(session, buf);
if (ret > 0) {
readBytes = ret;
}
}
} finally {
buf.flip();
}
if (readBytes > 0) {
IoFilterChain filterChain = session.getFilterChain();
filterChain.fireMessageReceived(buf);
buf = null;
if (hasFragmentation) {
if (readBytes << 1 < config.getReadBufferSize()) {
session.decreaseReadBufferSize();
} else if (readBytes == config.getReadBufferSize()) {
session.increaseReadBufferSize();
}
}
}
if (ret < 0) {
scheduleRemove(session);
}
} catch (Throwable e) {
if (e instanceof IOException) {
if (!(e instanceof PortUnreachableException)
|| !AbstractDatagramSessionConfig.class.isAssignableFrom(config.getClass())
|| ((AbstractDatagramSessionConfig) config).isCloseOnPortUnreachable()) {
scheduleRemove(session);
}
}
IoFilterChain filterChain = session.getFilterChain();
filterChain.fireExceptionCaught(e);
}
}
1、read(session, buf)
protected int read(NioSession session, IoBuffer buf) throws Exception {
ByteChannel channel = session.getChannel();
return channel.read(buf.buf());
}
2、filterChain.fireMessageReceived(buf);DefaultIoFilterChain类中的方法。过滤器链的设置和客户端设置的一致,不再累述。
public void fireMessageReceived(Object message) {
if (message instanceof IoBuffer) {
session.increaseReadBytes(((IoBuffer) message).remaining(), System.currentTimeMillis());
}
Entry head = this.head;
callNextMessageReceived(head, session, message);
}
read数据的时候从过滤器链首位过滤器开始往后执行,和write数据的时候刚好相反。
callNextMessageReceived()
private void callNextMessageReceived(Entry entry, IoSession session, Object message) {
try {
IoFilter filter = entry.getFilter();
NextFilter nextFilter = entry.getNextFilter();
filter.messageReceived(nextFilter, session, message);
} catch (Throwable e) {
fireExceptionCaught(e);
}
}
那么filter.messageReceived(nextFilter, session, message);调用HeadFilter父类IoFilterAdapter的方法
其他业务系统定义的过滤器,其过滤的逻辑是卸载此方法中的。
public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
nextFilter.messageReceived(session, message);
}
EntryImpl内部类NextFilter,取过滤器链的下一个过滤器执行。
public void messageReceived(IoSession session, Object message) {
Entry nextEntry = EntryImpl.this.nextEntry;
callNextMessageReceived(nextEntry, session, message);
}
最后会执行末位过滤器EntryImpl对象tail的方法
public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
AbstractIoSession s = (AbstractIoSession) session;
if (!(message instanceof IoBuffer)) {
s.increaseReadMessages(System.currentTimeMillis());
} else if (!((IoBuffer) message).hasRemaining()) {
s.increaseReadMessages(System.currentTimeMillis());
}
try {
session.getHandler().messageReceived(s, message);
} finally {
if (s.getConfig().isUseReadOperation()) {
s.offerReadFuture(message);
}
}
}
session.getHandler().messageReceived(s, message);调用服务启动时设置的handler,将读到的数据交由业务系统处理。
服务端读到数据后处理完业务,如果有数据返回也会使用session.write(Object object);和客户端写数据一样,先走一遍过滤器,再往通道中写。
而客户端读到数据,也和上面一样,先走一遍过滤器,不过略有区别的是,我们的客户端没有使用handler(客户端没有handler不会报异常。服务端是一定要的,在bind方法回去判断是否为空)。直接用session.read()方法死等:ReadFuture rf = session.read().awaitUninterruptibly();awaitUninterruptibly()在建立客户端的时候类似。等一会儿判断开关ready是否true,没有再等一会儿,而read的开关并非在初始化session的时候打开的。
从头捋一捋,客户端也是NioProcessor监听OP_READ,收到数据后进入过滤器链,到末位过滤器tail后,也就是上面那段代码,因为客户端设置了connector.getSessionConfig().setUseReadOperation(true);所以会执行finally中的s.offerReadFuture(message);AbstractIoSession类
public final void offerReadFuture(Object message) {
newReadFuture().setRead(message);
}
private ReadFuture newReadFuture() {
Queue<ReadFuture> readyReadFutures = getReadyReadFutures();
Queue<ReadFuture> waitingReadFutures = getWaitingReadFutures();
ReadFuture future;
synchronized (readyReadFutures) {
future = waitingReadFutures.poll();
if (future == null) {
future = new DefaultReadFuture(this);
readyReadFutures.offer(future);
}
}
return future;
}
取一个future,没有就创建一个DefaultReadFuture对象。
public void setRead(Object message) {
if (message == null) {
throw new IllegalArgumentException("message");
}
setValue(message);
}
public void setValue(Object newValue) {
synchronized (lock) {
// Allow only once.
if (ready) {
return;
}
result = newValue;
ready = true;
if (waiters > 0) {
lock.notifyAll();
}
}
notifyListeners();
}
这个开关到这里就打开了,而这个result就是服务端写入的数据,接下来的DefaultReadFuture.getMessage()取得就是这个值。