Apache mina设置写(write)buffer以及原理
对于我前一篇论述mina的read buffer大小设置以及mina对其自动控制的奥秘http://414149609.iteye.com/admin/blogs/1185777
本文重点论述一下mina发送端都发送分包的奥秘进行论述,还是以前篇(上面链接)所在的服务器客户端作为原型,可以进入链接查看。
mina的把需要发送的数据(包括对象,字节等数据)都转换为IoBuffer的子类,IoBuffer其实就是原来jdk中提供nio实现的Buffer的包装类。
也就是说最后的数据会转换为字节通过socket建立的channel发送出去的。
与前篇文章想对等,write和read的动作都在org.apache.mina.transport.socket.nio.NioProcessor
实现。请看代码
@Override protected int write(NioSession session, IoBuffer buf, int length) throws Exception { if (buf.remaining() <= length) { return session.getChannel().write(buf.buf()); } int oldLimit = buf.limit(); buf.limit(buf.position() + length); try { return session.getChannel().write(buf.buf()); } finally { buf.limit(oldLimit); } }
// Set limitation for the number of written bytes for read-write // fairness. I used maxReadBufferSize * 3 / 2, which yields best // performance in my experience while not breaking fairness much. final int maxWrittenBytes = session.getConfig().getMaxReadBufferSize() + (session.getConfig().getMaxReadBufferSize() >>> 1);
int localWrittenBytes = 0; Object message = req.getMessage(); if (message instanceof IoBuffer) { localWrittenBytes = writeBuffer(session, req, hasFragmentation, maxWrittenBytes - writtenBytes, currentTime); if (localWrittenBytes > 0 && ((IoBuffer) message).hasRemaining()) { // the buffer isn't empty, we re-interest it in writing writtenBytes += localWrittenBytes; setInterestedInWrite(session, true); return false; } } else if (message instanceof FileRegion) { localWrittenBytes = writeFile(session, req, hasFragmentation, maxWrittenBytes - writtenBytes, currentTime); // Fix for Java bug on Linux http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5103988 // If there's still data to be written in the FileRegion, return 0 indicating that we need // to pause until writing may resume. if (localWrittenBytes > 0 && ((FileRegion) message).getRemainingBytes() > 0) { writtenBytes += localWrittenBytes; setInterestedInWrite(session, true); return false; } } else { throw new IllegalStateException( "Don't know how to handle message of type '" + message.getClass().getName() + "'. Are you missing a protocol encoder?"); }
@Override protected int transferFile(NioSession session, FileRegion region, int length) throws Exception { try { return (int) region.getFileChannel().transferTo(region.getPosition(), length, session.getChannel()); } catch (IOException e) { // Check to see if the IOException is being thrown due to // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5103988 String message = e.getMessage(); if (message != null && message.contains("temporarily unavailable")) { return 0; } throw e; } }
public abstract long transferTo(long position, long count, WritableByteChannel target)