上一章分析了processHandles函数,本章开始将要分析processHandles中的process函数,该函数是处理客户端请求的核心函数。process定义在AbstractPollingIoProcessor中,
private void process() throws Exception {
for (Iterator<S> i = selectedSessions(); i.hasNext();) {
S session = i.next();
process(session);
i.remove();
}
}
这里就是依次取出Nio中发生相应时间的NioSocketSession,并进一步执行process函数,
private void process(S session) {
if (isReadable(session) && !session.isReadSuspended()) {
read(session);
}
if (isWritable(session) && !session.isWriteSuspended()) {
if (session.setScheduledForFlush(true)) {
flushingSessions.add(session);
}
}
}
isReadable和isWritable用于判断Nio中产生的key是哪种时间,isReadSuspended和isWriteSuspended则就是两个bool变量,用于控制读写。下面假设判定通过,如果是写事件,则很简单,将该Session添加进flushingSessions后,后续便能写入写缓存中(查看上一章的flush函数)。这里主要分析读事件,
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();
}
}
}
} catch (Exception e) {
}
}
该函数主要做了两件事情,一是调用read通过Nio的Channel将数据读进缓存中,二是调用IoFilterChain的fireMessageReceived函数。先看read函数,具体的读函数read定义在NioProcessor中,
protected int read(NioSession session, IoBuffer buf) throws Exception {
ByteChannel channel = session.getChannel();
return channel.read(buf.buf());
}
这里就是简单的调用Nio的Channel将数据读入缓存,具体的过程可以参考Nio的源码。
回到前面的read函数中,如果读入数据成功,就从NioSocketSession中获取IoFilterChain并调用其fireMessageReceived函数,getFilterChain返回的IoFilterChain是DefaultIoFilterChain。
在使用mina框架时,开发者可以定义自己的过滤器添加进mina中,mina默认实现了两个过滤器,看DefaultIoFilterChain的构造函数,
public DefaultIoFilterChain(AbstractIoSession session) {
if (session == null) {
throw new IllegalArgumentException("session");
}
this.session = session;
head = new EntryImpl(null, null, "head", new HeadFilter());
tail = new EntryImpl(head, null, "tail", new TailFilter());
head.nextEntry = tail;
}
因此,mina框架默认实现了HeadFilter和TailFilter。
fireMessageReceived定义在DefaultIoFilterChain中,
public void fireMessageReceived(Object message) {
if (message instanceof IoBuffer) {
session.increaseReadBytes(((IoBuffer) message).remaining(), System.currentTimeMillis());
}
callNextMessageReceived(head, session, message);
}
这里就是简单调用callNextMessageReceived进行进一步的处理,传入的参数head是过滤器链表的指针头,session是NioSocketSession,message就是读入的数据。
private void callNextMessageReceived(Entry entry, IoSession session, Object message) {
try {
IoFilter filter = entry.getFilter();
NextFilter nextFilter = entry.getNextFilter();
filter.messageReceived(nextFilter, session, message);
} catch (Exception e) {
}
}
这里就是从entry中取出过滤器filter,调用其messageReceived函数。默认必然会取出2个filter,一个是HeadFilter,另一个是TailFilter。其中,HeadFilter在处理消息时什么都不会做,TailFilter的messageReceived如下
public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
AbstractIoSession s = (AbstractIoSession) session;
try {
session.getHandler().messageReceived(s, message);
} finally {
if (s.getConfig().isUseReadOperation()) {
s.offerReadFuture(message);
}
}
}
因此,TailFilter会调用其中的注册的handler对消息进行处理,getHandler返回的是一个IoHandler。