鍦╪ioworker鐨勶紝璐熻矗璇誨彇鎿嶄綔鏄敱錛屽湪璇ユ柟娉曚腑錛屽鏋滃綋鍓峜hannel鐨?readyOps & SelectionKey.OP_READ) != 0 || readyOps == 0錛屼笖姝ゆ椂
ch.read(buff)<0,鍒欏垽鏂鎴風宸茬粡鏂紑榪炴帴
private boolean read(SelectionKey k) {
final SocketChannel ch = (SocketChannel) k.channel();
final NioSocketChannel channel = (NioSocketChannel) k.attachment();
final ReceiveBufferSizePredictor predictor =
channel.getConfig().getReceiveBufferSizePredictor();
//榛樿1024涓瓧鑺傜┖闂?/span>
final int predictedRecvBufSize = predictor.nextReceiveBufferSize();
int ret = 0;
int readBytes = 0;
boolean failure = true;
//鍒嗛厤榪炵畫鐨?024涓猙yte絀洪棿
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);
//瑙﹀彂娑堟伅鎺ユ敹浜嬩歡錛屾牴鎹畃ipeline涓璾pstreamhandler鐢變笂鍒頒笅鐨勯『搴忥紝璋冪敤messageReceived鏂規硶
fireMessageReceived(channel, buffer);
} else {
recvBufferPool.release(bb);
}
if (ret < 0 || failure) {
close(channel, succeededFuture(channel));
return false;
}
return true;
}
鍦╬ipelinefactory涓殑絎竴涓猽pstreamhandler涓篋elimiterBasedFrameDecoder錛岀戶鎵胯嚜FrameDecoder
public ChannelPipeline getPipeline() throws Exception {
// Create a default pipeline implementation.
ChannelPipeline pipeline = pipeline();
// Add the text line codec combination first,
pipeline.addLast("framer", new DelimiterBasedFrameDecoder(
8192, Delimiters.lineDelimiter()));
pipeline.addLast("decoder", new StringDecoder());
pipeline.addLast("encoder", new StringEncoder());
// and then business logic.
pipeline.addLast("handler", new TelnetServerHandler());
return pipeline;
}
浼氳皟鐢‵rameDecoder鐨刴essageReceived
public void messageReceived(
ChannelHandlerContext ctx, MessageEvent e) throws Exception {
Object m = e.getMessage();
if (!(m instanceof ChannelBuffer)) {
ctx.sendUpstream(e);
return;
}
ChannelBuffer input = (ChannelBuffer) m;
if (!input.readable()) {
return;
}
ChannelBuffer cumulation = cumulation(ctx);
if (cumulation.readable()) {
cumulation.discardReadBytes();
cumulation.writeBytes(input);
callDecode(ctx, e.getChannel(), cumulation, e.getRemoteAddress());
} else {
//榪欓噷璋冪敤瀛愮被鐨刣ecode鏂規硶
callDecode(ctx, e.getChannel(), input, e.getRemoteAddress());
if (input.readable()) {
cumulation.writeBytes(input);
}
}
}
//鍦ㄨ繖涓猽pstreamhandler涓紝浼氫竴鐩磋鍙栨暟鎹紝鐩村埌閬囧埌鍗忚綰﹀畾鐨勭粨鏉熸爣蹇楁墠灝唌essagereceived浜嬩歡浼犵粰涓嬩竴涓?br />
private void callDecode(
ChannelHandlerContext context, Channel channel,
ChannelBuffer cumulation, SocketAddress remoteAddress) throws Exception {
while (cumulation.readable()) {
int oldReaderIndex = cumulation.readerIndex();
Object frame = decode(context, channel, cumulation);
if (frame == null) {
if (oldReaderIndex == cumulation.readerIndex()) {
// Seems like more data is required.
// Let us wait for the next notification.
break;
} else {
// Previous data has been discarded.
// Probably it is reading on.
continue;
}
} else if (oldReaderIndex == cumulation.readerIndex()) {
throw new IllegalStateException(
"decode() method must read at least one byte " +
"if it returned a frame (caused by: " + getClass() + ")");
}
//灝唌essagereceive浜嬩歡浼犵粰涓嬩釜upstreamhandler
unfoldAndFireMessageReceived(context, remoteAddress, frame);
}
}
鐪嬪瓙綾葷殑decode鏄浣曞垽鏂暟鎹鍙栧畬姣?br />
protected Object decode(
ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
// Try all delimiters and choose the delimiter which yields the shortest frame.
int minFrameLength = Integer.MAX_VALUE;
ChannelBuffer minDelim = null;
//鑾峰彇\r\n鐨勪綅緗?/span>
for (ChannelBuffer delim: delimiters) {
int frameLength = indexOf(buffer, delim);
if (frameLength >= 0 && frameLength < minFrameLength) {
minFrameLength = frameLength;
minDelim = delim;
}
}
//濡傛灉鎵懼埌\r\n錛岃〃鏄庡鎴風鏁版嵁鍙戦佸畬姣?/span>
if (minDelim != null) {
int minDelimLength = minDelim.capacity();
ChannelBuffer frame;
if (discardingTooLongFrame) {
// We've just finished discarding a very large frame.
// Go back to the initial state.
discardingTooLongFrame = false;
buffer.skipBytes(minFrameLength + minDelimLength);
// TODO Let user choose when the exception should be raised - early or late?
// If early, fail() should be called when discardingTooLongFrame is set to true.
int tooLongFrameLength = this.tooLongFrameLength;
this.tooLongFrameLength = 0;
fail(ctx, tooLongFrameLength);
return null;
}
if (minFrameLength > maxFrameLength) {
// Discard read frame.
buffer.skipBytes(minFrameLength + minDelimLength);
fail(ctx, minFrameLength);
return null;
}
if (stripDelimiter) {
//榪欓噷璇誨彇鍏ㄩ儴鏁版嵁
frame = buffer.readBytes(minFrameLength);
buffer.skipBytes(minDelimLength);
} else {
frame = buffer.readBytes(minFrameLength + minDelimLength);
}
return frame;
} else {
if (!discardingTooLongFrame) {
if (buffer.readableBytes() > maxFrameLength) {
// Discard the content of the buffer until a delimiter is found.
tooLongFrameLength = buffer.readableBytes();
buffer.skipBytes(buffer.readableBytes());
discardingTooLongFrame = true;
}
} else {
// Still discarding the buffer since a delimiter is not found.
tooLongFrameLength += buffer.readableBytes();
buffer.skipBytes(buffer.readableBytes());
}
return null;
}
}
鍥犱負unfold榛樿鏄痜alse錛屼細鎵ц錛岃皟鐢ㄤ笅涓涓猽pstreamhandler錛岃繖閲屾槸stringdecoder錛岄氳繃stringdecoder錛屽皢channelbuffer涓殑鏁版嵁杞負string
鐒跺悗鍐嶈Е鍙戜笅涓涓猽pstreamhandler鐨刴essagereceive錛岃繖閲屾槸TelnetServerHandler
public void messageReceived(
ChannelHandlerContext ctx, MessageEvent e) {
// Cast to a String first.
// We know it is a String because we put some codec in TelnetPipelineFactory.
String request = (String) e.getMessage();
// Generate and write a response.
String response;
boolean close = false;
if (request.length() == 0) {
response = "Please type something."r"n";
} else if (request.toLowerCase().equals("bye")) {
response = "Have a good day!"r"n";
close = true;
} else {
response = "Did you say '" + request + "'?"r"n";
}
// We do not need to write a ChannelBuffer here.
// We know the encoder inserted at TelnetPipelineFactory will do the conversion.
ChannelFuture future = e.getChannel().write(response);
// Close the connection after sending 'Have a good day!'
// if the client has sent 'bye'.
if (close) {
future.addListener(ChannelFutureListener.CLOSE);
}
}
鏁版嵁璇誨彇鍒嗘瀽瀹屾瘯錛屾帴鐫緇х畫鍒嗘瀽鏈嶅姟鍣ㄧ鏁版嵁鐨勫彂閫?br />

]]>