最近在看netty源码,遇到一个问题一直没有想明白,而且又牵扯出了其他的问题。
在netty源码中通过NioWorker作为一个selector进行轮询事件,同时对每一个channel都有一个buffer预言者,预言下一次到达的buffer大小。
private boolean read(SelectionKey k) {
final SocketChannel ch = (SocketChannel) k.channel();
final NioSocketChannel channel = (NioSocketChannel) k.attachment(); final ReceiveBufferSizePredictor predictor =
channel.getConfig().getReceiveBufferSizePredictor();
final int predictedRecvBufSize = predictor.nextReceiveBufferSize(); int ret = 0;
int readBytes = 0;
boolean failure = true; ByteBuffer bb = recvBufferPool.acquire(predictedRecvBufSize);
try {
while ((ret = ch.read(bb)) > 0) {
readBytes += ret;
if (!bb.hasRemaining()) {
break;
}
}
failure = false;
} catch (ClosedChannelException e) {
// Can happen, and does not need a user attention.
} catch (Throwable t) {
fireExceptionCaught(channel, t);
} if (readBytes > 0) {
bb.flip(); final ChannelBufferFactory bufferFactory =
channel.getConfig().getBufferFactory();
final ChannelBuffer buffer = bufferFactory.getBuffer(readBytes);
buffer.setBytes(0, bb);
buffer.writerIndex(readBytes); recvBufferPool.release(bb); // Update the predictor.
predictor.previousReceiveBufferSize(readBytes); // Fire the event.
fireMessageReceived(channel, buffer);
} else {
recvBufferPool.release(bb);
} if (ret < 0 || failure) {
k.cancel(); // Some JDK implementations run into an infinite loop without this.
close(channel, succeededFuture(channel));
return false;
} return true;
}
原始的预言大小为1024,那么当我直接向netty服务端发送一个2048大小的字符时,我发现它第一次select到了事件后先读取了1024,然后发现buffer没有空间了,就结束这次读,然后再轮询时,又出现了一个读事件,猜测是否selector在执行select时都会对每一个注册来的sk的channel进行检测,如果channel中还存在数据就会认为此时已准备好读,就会添加selectedkey呢?
看了一些sun.nio中的源码,不过还不是很清楚,求高人指点下,多谢。
在netty源码中通过NioWorker作为一个selector进行轮询事件,同时对每一个channel都有一个buffer预言者,预言下一次到达的buffer大小。
private boolean read(SelectionKey k) {
final SocketChannel ch = (SocketChannel) k.channel();
final NioSocketChannel channel = (NioSocketChannel) k.attachment(); final ReceiveBufferSizePredictor predictor =
channel.getConfig().getReceiveBufferSizePredictor();
final int predictedRecvBufSize = predictor.nextReceiveBufferSize(); int ret = 0;
int readBytes = 0;
boolean failure = true; ByteBuffer bb = recvBufferPool.acquire(predictedRecvBufSize);
try {
while ((ret = ch.read(bb)) > 0) {
readBytes += ret;
if (!bb.hasRemaining()) {
break;
}
}
failure = false;
} catch (ClosedChannelException e) {
// Can happen, and does not need a user attention.
} catch (Throwable t) {
fireExceptionCaught(channel, t);
} if (readBytes > 0) {
bb.flip(); final ChannelBufferFactory bufferFactory =
channel.getConfig().getBufferFactory();
final ChannelBuffer buffer = bufferFactory.getBuffer(readBytes);
buffer.setBytes(0, bb);
buffer.writerIndex(readBytes); recvBufferPool.release(bb); // Update the predictor.
predictor.previousReceiveBufferSize(readBytes); // Fire the event.
fireMessageReceived(channel, buffer);
} else {
recvBufferPool.release(bb);
} if (ret < 0 || failure) {
k.cancel(); // Some JDK implementations run into an infinite loop without this.
close(channel, succeededFuture(channel));
return false;
} return true;
}
原始的预言大小为1024,那么当我直接向netty服务端发送一个2048大小的字符时,我发现它第一次select到了事件后先读取了1024,然后发现buffer没有空间了,就结束这次读,然后再轮询时,又出现了一个读事件,猜测是否selector在执行select时都会对每一个注册来的sk的channel进行检测,如果channel中还存在数据就会认为此时已准备好读,就会添加selectedkey呢?
看了一些sun.nio中的源码,不过还不是很清楚,求高人指点下,多谢。
解决方案 »
免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货