˜q›è¡Œäº?ji¨£n)å°è£…ï¼Œå¢žåŠ äº†(ji¨£n)一些实用的æ–ÒŽ(gu¨©)³•ã€?/span>
ChannelBuf 接å£
package io.netty.buffer;public interface ChannelBuf { ChannelBufType type(); boolean isPooled(); }
ByteBuf 接å£
package io.netty.buffer;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.nio.ByteBuffer;import java.nio.ByteOrder;import java.nio.channels.GatheringByteChannel;import java.nio.channels.ScatteringByteChannel;import java.nio.charset.Charset;import java.nio.charset.UnsupportedCharsetException;public interface ByteBuf extends ChannelBuf, Comparable<ByteBuf> { int capacity(); ByteBuf capacity(int newCapacity); int maxCapacity(); ByteOrder order(); ByteBuf order(ByteOrder endianness); boolean isDirect(); int readerIndex(); ByteBuf readerIndex(int readerIndex); int writerIndex(); ByteBuf writerIndex(int writerIndex); ByteBuf setIndex(int readerIndex, int writerIndex); int readableBytes(); int writableBytes(); boolean readable(); boolean writable(); ByteBuf clear(); ByteBuf markReaderIndex(); ByteBuf resetReaderIndex(); ByteBuf markWriterIndex(); ByteBuf resetWriterIndex(); ByteBuf discardReadBytes(); ByteBuf ensureWritableBytes(int minWritableBytes); int ensureWritableBytes(int minWritableBytes, boolean force); boolean getBoolean(int index); byte getByte(int index); short getUnsignedByte(int index); short getShort(int index); int getUnsignedShort(int index); int getMedium(int index); int getUnsignedMedium(int index); int getInt(int index); long getUnsignedInt(int index); long getLong(int index); char getChar(int index); float getFloat(int index); double getDouble(int index); ByteBuf getBytes(int index, ByteBuf dst); ByteBuf getBytes(int index, ByteBuf dst, int length); ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length); ByteBuf getBytes(int index, byte [] dst); ByteBuf getBytes(int index, byte [] dst, int dstIndex, int length); ByteBuf getBytes(int index, ByteBuffer dst); ByteBuf getBytes(int index, OutputStream out, int length) throws IOException; int getBytes(int index, GatheringByteChannel out, int length) throws IOException; ByteBuf setBoolean(int index, boolean value); ByteBuf setByte(int index, int value); ByteBuf setShort(int index, int value); ByteBuf setMedium(int index, int value); ByteBuf setInt(int index, int value); ByteBuf setLong(int index, long value); ByteBuf setChar(int index, int value); ByteBuf setFloat(int index, float value); ByteBuf setDouble(int index, double value); ByteBuf setBytes(int index, ByteBuf src); ByteBuf setBytes(int index, ByteBuf src, int length); ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length); ByteBuf setBytes(int index, byte [] src); ByteBuf setBytes(int index, byte [] src, int srcIndex, int length); ByteBuf setBytes(int index, ByteBuffer src); int setBytes(int index, InputStream in, int length) throws IOException; int setBytes(int index, ScatteringByteChannel in, int length) throws IOException; ByteBuf setZero(int index, int length); boolean readBoolean(); byte readByte(); short readUnsignedByte(); short readShort(); int readUnsignedShort(); int readMedium(); int readUnsignedMedium(); int readInt(); long readUnsignedInt(); long readLong(); char readChar(); float readFloat(); double readDouble(); ByteBuf readBytes(int length); ByteBuf readSlice(int length); ByteBuf readBytes(ByteBuf dst); ByteBuf readBytes(ByteBuf dst, int length); ByteBuf readBytes(ByteBuf dst, int dstIndex, int length); ByteBuf readBytes(byte [] dst); ByteBuf readBytes(byte [] dst, int dstIndex, int length); ByteBuf readBytes(ByteBuffer dst); ByteBuf readBytes(OutputStream out, int length) throws IOException; int readBytes(GatheringByteChannel out, int length) throws IOException; ByteBuf skipBytes(int length); ByteBuf writeBoolean(boolean value); ByteBuf writeByte(int value); ByteBuf writeShort(int value); ByteBuf writeMedium(int value); ByteBuf writeInt(int value); ByteBuf writeLong(long value); ByteBuf writeChar(int value); ByteBuf writeFloat(float value); ByteBuf writeDouble(double value); ByteBuf writeBytes(ByteBuf src); ByteBuf writeBytes(ByteBuf src, int length); ByteBuf writeBytes(ByteBuf src, int srcIndex, int length); ByteBuf writeBytes(byte [] src); ByteBuf writeBytes(byte [] src, int srcIndex, int length); ByteBuf writeBytes(ByteBuffer src); int writeBytes(InputStream in, int length) throws IOException; int writeBytes(ScatteringByteChannel in, int length) throws IOException; ByteBuf writeZero(int length); int indexOf(int fromIndex, int toIndex, byte value); int indexOf(int fromIndex, int toIndex, ByteBufIndexFinder indexFinder); int bytesBefore(byte value); int bytesBefore(ByteBufIndexFinder indexFinder); int bytesBefore(int length, byte value); int bytesBefore(int length, ByteBufIndexFinder indexFinder); int bytesBefore(int index, int length, byte value); int bytesBefore(int index, int length, ByteBufIndexFinder indexFinder); ByteBuf copy(); ByteBuf copy(int index, int length); ByteBuf slice(); ByteBuf slice(int index, int length); ByteBuf duplicate(); boolean hasNioBuffer(); ByteBuffer nioBuffer(); ByteBuffer nioBuffer(int index, int length); boolean hasNioBuffers(); ByteBuffer[] nioBuffers(); ByteBuffer[] nioBuffers(int offset, int length); boolean hasArray(); byte [] array(); int arrayOffset(); String toString(Charset charset); String toString(int index, int length, Charset charset); @Override int hashCode(); @Override boolean equals(Object obj); @Override int compareTo(ByteBuf buffer); @Override String toString(); Unsafe unsafe(); interface Unsafe { ByteBuffer nioBuffer(); ByteBuffer[] nioBuffers(); ByteBuf newBuffer(int initialCapacity); void discardSomeReadBytes(); void acquire(); void release(); } }
ByteBuf Index
ByteBuf 通过两个指针æ¥ååŠ?/span>I/O 的读写æ“作,è¯ÀL“作的 readIndex 和写æ“作çš?/span>writeIndex
readerIndex å’?/span>writerIndex 都是一开始都æ˜?/span>0 åQŒéšç€æ•°æ®çš„写å…?/span>writerIndex ä¼?x¨¬)å¢žåŠ ï¼Œè¯Õd–æ•°æ®ä¼?x¨¬)ä‹?/span>readerIndex å¢žåŠ åQŒä½†æ˜¯ä»–ä¸ä¼š(x¨¬)‘…过 writerIndx åQŒåœ¨è¯Õd–之åŽåQ?/span>0-readerIndex 的就被视ä¸?/span>discard çš?/span>. 调用 discardReadBytes æ–ÒŽ(gu¨©)³• , å¯ä»¥é‡Šæ”¾˜q™éƒ¨åˆ†ç©ºé—?/span>, 他的作用¾cÖM¼¼ ByeBuffer çš?/span>compact æ–ÒŽ(gu¨©)³• ;
è¯Õd’Œå†™çš„æ—¶å€?/span>Index æ˜¯åˆ†å¼€çš„ï¼Œå› æ¤ä¹Ÿå°±æ²¡å¿…è¦å†æ¯æ¬¡è¯Õd®Œä»¥åŽè°ƒç”¨ flip æ–ÒŽ(gu¨©)³•åQŒå¦å¤–还æœ?/span>indexOf ã€?/span>bytesBefore ½{‰ä¸€äº›æ–¹ä¾¿çš„æ–ÒŽ(gu¨©)³•åQ?/span>
ByteBuf çš„å‡ ä¸ªé‡è¦æ–¹æ³?/span>
discardReadBytes() 丢弃已读的内å®V€‚其执行˜q‡ç¨‹å¦‚下åQ?/span> 调用discardReadBytes() 之å‰åQ?/span>
调用 discardReadBytes() æ–ÒŽ(gu¨©)³•å?/span>
clear() 丢弃所有的数æ®åQŒåƈž®?span style="font-size: 6.5pt; font-family: 'Courier New'; background-position: initial initial; background-repeat: initial initial;">readerIndex å’?/span>writerIndex é‡ç½®ä¸?/span>0 ã€?/span>
调用clear() 之å‰
调用 clear() 之åŽ
备注:å› äØ“(f¨´)½W”者开始写Nettyæºç 分æžçš„æ—¶å€™ï¼ŒNetty 4.0˜q˜æ˜¯å¤„于Alpha阶段åQŒä¹‹åŽçš„APIå¯èƒ½˜q˜ä(sh¨´)¼š(x¨¬)有改动,½W”者将ä¼?x¨¬)å?qi¨¢ng)æ—¶æ›´æ”V€‚ä‹É用开æºå·²¾læœ‰å¥½å‡ òq´çš„æ—‰™—´äº?ji¨£n),一直没有时间和¾_‘ÖŠ›æ¥å…·ä½“ç ”½I¶æŸä¸ªå¼€æºé¡¹ç›®çš„具体实现åQŒè¿™‹Æ¡æ˜¯½W¬ä¸€‹Æ¡å†™å¼€æºé¡¹ç›®çš„æºç 分æžåQŒå¦‚æžœæ–‡ä¸æœ‰é”™è¯¯çš„地方,‹Æ¢è¿Žè¯»è€…å¯ä»¥ç•™a€æŒ‡å‡ºã€‚对于è{载的读者,è¯äh³¨æ˜Žæ–‡ç« 的出处ã€?/p>
希望和广大的开å‘è€?å¼€æºçˆ±å¥½è€…进行交‹¹ï¼Œ‹Æ¢è¿Žå¤§å®¶çš„ç•™a€å’Œè®¨è®ºã€?/div>
]]>
Netty 4.0 æºç 分æžåQˆäº”åQ‰ï¼š(x¨¬)ChannelHandlerContextå’ŒChannelHandler http://www.aygfsteel.com/czihong/articles/391932.htmlChan Chen Chan Chen Sun, 25 Nov 2012 08:51:00 GMT http://www.aygfsteel.com/czihong/articles/391932.html http://www.aygfsteel.com/czihong/comments/391932.html http://www.aygfsteel.com/czihong/articles/391932.html#Feedback 3 http://www.aygfsteel.com/czihong/comments/commentRss/391932.html http://www.aygfsteel.com/czihong/services/trackbacks/391932.html ChannelHandlerContext 接å£
1 package io.netty.channel;
2 import io.netty.buffer.ByteBuf;
3 import io.netty.buffer.MessageBuf;
4 import io.netty.util.AttributeMap;
5 import java.nio.channels.Channels;
6 import java.util.Set;
7 public interface ChannelHandlerContext
8 extends AttributeMap, ChannelFutureFactory,
9 ChannelInboundInvoker, ChannelOutboundInvoker {
10 Channel channel();
11 ChannelPipeline pipeline();
12 EventExecutor executor();
13 String name();
14 ChannelHandler handler();
15 Set<ChannelHandlerType> types();
16 boolean hasInboundByteBuffer();
17 boolean hasInboundMessageBuffer();
18 ByteBuf inboundByteBuffer();
19 <T> MessageBuf<T> inboundMessageBuffer();
20 boolean hasOutboundByteBuffer();
21 boolean hasOutboundMessageBuffer();
22 ByteBuf outboundByteBuffer();
23 <T> MessageBuf<T> outboundMessageBuffer();
24 ByteBuf replaceInboundByteBuffer(ByteBuf newInboundByteBuf);
25 <T> MessageBuf<T> replaceInboundMessageBuffer(MessageBuf<T> newInboundMsgBuf);
26 ByteBuf replaceOutboundByteBuffer(ByteBuf newOutboundByteBuf);
27 <T> MessageBuf<T> replaceOutboundMessageBuffer(MessageBuf<T> newOutboundMsgBuf);
28 boolean hasNextInboundByteBuffer();
29 boolean hasNextInboundMessageBuffer();
30 ByteBuf nextInboundByteBuffer();
31 MessageBuf<Object> nextInboundMessageBuffer();
32 boolean hasNextOutboundByteBuffer();
33 boolean hasNextOutboundMessageBuffer();
34 ByteBuf nextOutboundByteBuffer();
35 MessageBuf<Object> nextOutboundMessageBuffer();
36 boolean isReadable();
37 void readable(boolean readable);
38 }
ChannelHandlerContext æŽ¥å£ UML ¾c?/span>
ChannelHandlerContext 接å£çš„å‡ ä¸ªé‡è¦æ–¹æ³?/span>
ChannelPipeline pipeline();
˜q”å›žå±žäºŽå½“å‰ ChannelHandlerContext çš?/span>ChannelPipeline ã€?/span>
EventExecutor executor();
EnventExcutor 用于调度 EventLoop ä¸çš„ event åQŒè¿™ä¸ªæ–¹æ³•返回当å‰çš„ EventExecutor ã€?/span>
一ä¸?/span>Handler å¯ä»¥æœ‰å¤šä¸?/span>Context
一ä¸?/span>Handler å¯ä»¥è¢«æ·»åŠ åˆ°å¤šä¸ª ChannelPipeline 。这ž®±æ„味ç€ä¸€ä¸?/span>ChannelHandler å¯ä»¥æœ‰å¤šä¸?/span>ChannelHandlerContext ã€?/span>
ChannelHandler 接å£
1 package io.netty.channel;
2
3 import io.netty.channel.group.ChannelGroup;
4 import java.lang.annotation.Documented;
5 import java.lang.annotation.ElementType;
6 import java.lang.annotation.Inherited;
7 import java.lang.annotation.Retention;
8 import java.lang.annotation.RetentionPolicy;
9 import java.lang.annotation.Target;
10 import java.nio.channels.Channels;
11
12 public interface ChannelHandler {
13 void beforeAdd(ChannelHandlerContext ctx) throws Exception;
14 void afterAdd(ChannelHandlerContext ctx) throws Exception;
15 void beforeRemove(ChannelHandlerContext ctx) throws Exception;
16 void afterRemove(ChannelHandlerContext ctx) throws Exception;
17 void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception;
18 void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception;
19 @Inherited
20 @Documented
21 @Target(ElementType.TYPE)
22 @Retention(RetentionPolicy.RUNTIME)
23 @interface Sharable {
24 // no value
25 }
26 }
ChannelHandler ¾c?/span>UML å›?/span>
ChannelHandler ä¸çš„å‡ ä¸ªé‡è¦æ–ÒŽ(gu¨©)³•
ChannelHandler æœ‰ä¸¤ä¸ªåæŽ¥å£åQ?/span>ChannelUpstreamHandler å’?/span>ChannelDownstreamHandler ã€?/span>
1. ChannelUpstreamHandler 用于处ç†å’Œæ‹¦æˆ?/span>upstream ä¸çš„ ChannelEvent
2. ChannelDownstreamHandler 用于处ç†å’Œæ‹¦æˆ?/span>downstream ä¸çš„ ChannelEvent
状æ€ä¿¡æ?/span>
ChannelHandler 一般需è¦å˜å‚¨ä¸€äº›çжæ€ä¿¡æ¯ï¼Œä»¥ä¸‹æ˜¯ã€å®˜æ–ÒŽ(gu¨©)ލè】的æ–ÒŽ(gu¨©)³•åQŒä‹É用æˆå‘˜å˜é‡ã€?/span>
public class DataServerHandler
extends SimpleChannelHandler {
private boolean loggedIn;
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
Channel ch = e.getChannel();
Object o = e.getMessage();
if (o
instanceof LoginMessage) {
authenticate((LoginMessage) o);
loggedIn =
true ;
}
else (o
instanceof GetDataMessage) {
if (loggedIn) {
ch.write(fetchSecret((GetDataMessage) o));
}
else {
fail();
}
}
}
}
// Create a new handler instance per channel.
// See ClientBootstrap#setPipelineFactory(ChannelPipelineFactory).
public class DataServerPipelineFactory
implements ChannelPipelineFactory {
public ChannelPipeline getPipeline() {
return Channels.pipeline(
new DataServerHandler());
}
}
或者ä‹Éç”?/span>ChannelLocal åQŒä»£ç 如ä¸?/span>
public final class DataServerState {
public static final ChannelLocal<Boolean> loggedIn =
new ChannelLocal<>() {
protected Boolean initialValue(Channel channel) {
return false ;
}
}
}
@Sharable
public class DataServerHandler
extends SimpleChannelHandler {
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
Channel ch = e.getChannel();
Object o = e.getMessage();
if (o
instanceof LoginMessage) {
authenticate((LoginMessage) o);
DataServerState.loggedIn.set(ch,
true );
}
else (o
instanceof GetDataMessage) {
if (DataServerState.loggedIn.get(ch)) {
ctx.getChannel().write(fetchSecret((GetDataMessage) o));
}
else {
fail();
}
}
}
}
// Print the remote addresses of the authenticated clients:
ChannelGroup allClientChannels =
;
for (Channel ch: allClientChannels) {
if (DataServerState.loggedIn.get(ch)) {
System.out.println(ch.getRemoteAddress());
}
}
备注:å› äØ“(f¨´)½W”者开始写Nettyæºç 分æžçš„æ—¶å€™ï¼ŒNetty 4.0˜q˜æ˜¯å¤„于Alpha阶段åQŒä¹‹åŽçš„APIå¯èƒ½˜q˜ä(sh¨´)¼š(x¨¬)有改动,½W”者将ä¼?x¨¬)å?qi¨¢ng)æ—¶æ›´æ”V€‚ä‹É用开æºå·²¾læœ‰å¥½å‡ òq´çš„æ—‰™—´äº?ji¨£n),一直没有时间和¾_‘ÖŠ›æ¥å…·ä½“ç ”½I¶æŸä¸ªå¼€æºé¡¹ç›®çš„具体实现åQŒè¿™‹Æ¡æ˜¯½W¬ä¸€‹Æ¡å†™å¼€æºé¡¹ç›®çš„æºç 分æžåQŒå¦‚æžœæ–‡ä¸æœ‰é”™è¯¯çš„地方,‹Æ¢è¿Žè¯»è€…å¯ä»¥ç•™a€æŒ‡å‡ºã€‚对于è{载的读者,è¯äh³¨æ˜Žæ–‡ç« 的出处ã€?希望和广大的开å‘è€?å¼€æºçˆ±å¥½è€…进行交‹¹ï¼Œ‹Æ¢è¿Žå¤§å®¶çš„ç•™a€å’Œè®¨è®ºã€?/div>
]]>Netty 4.0 æºç 分æžåQˆä¸‰åQ‰ï¼š(x¨¬)Channelå’ŒChannelPipeline http://www.aygfsteel.com/czihong/articles/391927.htmlChan Chen Chan Chen Sun, 25 Nov 2012 06:53:00 GMT http://www.aygfsteel.com/czihong/articles/391927.html http://www.aygfsteel.com/czihong/comments/391927.html http://www.aygfsteel.com/czihong/articles/391927.html#Feedback 0 http://www.aygfsteel.com/czihong/comments/commentRss/391927.html http://www.aygfsteel.com/czihong/services/trackbacks/391927.html 阅读全文 ]]> Netty 4.0 æºç 分æžåQˆäºŒåQ‰ï¼š(x¨¬)Echo Server http://www.aygfsteel.com/czihong/articles/391899.htmlChan Chen Chan Chen Sat, 24 Nov 2012 04:38:00 GMT http://www.aygfsteel.com/czihong/articles/391899.html http://www.aygfsteel.com/czihong/comments/391899.html http://www.aygfsteel.com/czihong/articles/391899.html#Feedback 1 http://www.aygfsteel.com/czihong/comments/commentRss/391899.html http://www.aygfsteel.com/czihong/services/trackbacks/391899.html Netty™å¹ç›®ä¸ï¼Œè‡ªå¸¦äº?ji¨£n)很多ä‹É用的例ååQŒå¯¹äºŽåˆšåˆšå¼€å§‹æŽ¥è§¦å’Œå¦ä¹ (f¨¤n) Nettyæºç 的开å‘者æ¥è¯ß_(d¨¢)¼Œå¯ä»¥é€šè¿‡ä¾‹åæ¥æ›´å¥½çš„ç†è§£ Netty的具体实现。æºç å¯ä»¥å†netty 4.0çš„example扑ֈ°ã€?/span>
1 public class EchoServerHandler extends ChannelInboundByteHandlerAdapter { 2 private static final Logger logger = Logger.getLogger( 3 EchoServerHandler.class .getName()); 4 5 @Override 6 public void inboundBufferUpdated(ChannelHandlerContext ctx, ByteBuf in) { 7 ByteBuf out = ctx.nextOutboundByteBuffer(); 8 out.discardReadBytes(); 9 out.writeBytes(in);10 ctx.flush();11 }12 13 @Override14 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {15 // Close the connection when an exception is raised. 16 logger.log(Level.WARNING, "Unexpected exception from downstream.", cause);17 ctx.close();18 }19 }
Line 1: 声明一ä¸?/span>EchoServerHandler, òq¶ä¸”¾l§æ‰¿äº?/span>ChannelInboundByteHandlerAdapter ã€?/span> ˜q™æ · EchoServerHandler ž®±å¯ä»¥å¤„ç?/span>client å‘é€è¿‡æ¥çš„ request ã€?/span>
Line 6: é‡å†™ inboundBufferUpdatedæ–ÒŽ(gu¨©)³•åQŒå¯¹ clientå‘é€è¿‡æ¥çš„ request˜q›è¡Œå¯?/span>ByteBuffer对象的æ“作。关äº?/span>ByteBuffer的概念将在以åŽç« 节讨论ã€?/span>
Line 7: ctx.nextOutboundByteBuffer () ž®†è¿”回一ä¸?/span>ByteBuffer 对象。如果该对象ä¸å˜åœ¨ï¼Œé‚£ä¹ˆæŠ›å‡º UnsupportedOperationException 异常ã€?/span>
Line 14: é‡å†™ exceptionCaughtåœ?/span>server端æ•获异常ã€?/span>
1 public class EchoServer { 2 3 private final int port; 4 5 public EchoServer(int port) { 6 this .port = port; 7 } 8 9 public void run() throws Exception {10 // Configure the server. 11 ServerBootstrap b = new ServerBootstrap();12 try {13 b.group(new NioEventLoopGroup(), new NioEventLoopGroup())14 .channel(NioServerSocketChannel.class )15 .option(ChannelOption.SO_BACKLOG, 100)16 .localAddress(new InetSocketAddress(port))17 .childOption(ChannelOption.TCP_NODELAY, true )18 .handler(new LoggingHandler(LogLevel.INFO))19 .childHandler(new ChannelInitializer<SocketChannel>() {20 @Override21 public void initChannel(SocketChannel ch) throws Exception {22 ch.pipeline().addLast(23 new LoggingHandler(LogLevel.INFO),24 new EchoServerHandler());25 }26 });27 28 // Start the server. 29 ChannelFuture f = b.bind().sync();30 31 // Wait until the server socket is closed. 32 f.channel().closeFuture().sync();33 } finally {34 // Shut down all event loops to terminate all threads. 35 b.shutdown();36 }37 }38 39 public static void main(String[] args) throws Exception {40 int port;41 if (args.length > 0) {42 port = Integer.parseInt(args[0]);43 } else {44 port = 8080;45 }46 new EchoServer(port).run();47 }48 }
Line 11: 通过 ServerBootStrap 对象åQŒæ¥å¯åЍæœåŠ¡å™?/span>
Line 13: 通过 groupæ–ÒŽ(gu¨©)³•åQŒæ¥¾l‘定 EventLoopGroupåQ?/span>EventLoopGroup用æ¥å¤„ç† SocketChannelå’?/span>Channel上é¢çš„æ‰€æœ‰æ—¶é—´å’Œ IOã€?/span>
Line 16: localAddressæ–ÒŽ(gu¨©)³•用于¾l‘定æœåŠ¡å™¨åœ°å€å’Œç«¯å£ã€?/span>
Line 18,19: handleræ–ÒŽ(gu¨©)³•å’?/span>childhandleræ–ÒŽ(gu¨©)³•用于指定å„ç§ ChannelHandler对象åQŒæŒ‡å®šçš„ ChannelHandler对象ž®†ç”¨äºŽå¤„ç?/span>client端æ¥çš?/span>requestã€?/span>
Line 21: åˆå§‹åŒ–一ä¸?/span>Channel对象åQŒåƈ且绑定之å‰å®šä¹‰çš„ EchoServerHandler¾c…R€?/span>
Line 22: ž®?/span>EchoServerHandleræ·ÕdŠ åˆ?/span>Pipelineä¸ã€?/span>
Line 29: ServerBootstrap对象准备ž®ÞqÈAåQŒå¯åŠ?/span>serveråQ?/span>
Line 32: ½{‰å¾…直到 server socketå…³é—
public class EchoClientHandler extends ChannelInboundByteHandlerAdapter { private static final Logger logger = Logger.getLogger( EchoClientHandler.class .getName()); private final ByteBuf firstMessage; /** * Creates a client-side handler. */ public EchoClientHandler(int firstMessageSize) { if (firstMessageSize <= 0) { throw new IllegalArgumentException("firstMessageSize: " + firstMessageSize); } firstMessage = Unpooled.buffer(firstMessageSize); for (int i = 0; i < firstMessage.capacity(); i ++) { firstMessage.writeByte((byte ) i); } } @Override public void channelActive(ChannelHandlerContext ctx) { ctx.write(firstMessage); } @Override public void inboundBufferUpdated(ChannelHandlerContext ctx, ByteBuf in) { ByteBuf out = ctx.nextOutboundByteBuffer(); out.discardReadBytes(); out.writeBytes(in); ctx.flush(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // Close the connection when an exception is raised. logger.log(Level.WARNING, "Unexpected exception from downstream.", cause); ctx.close(); } }
EchoClientHandler ¾cÈš„实现ä¸?/span>EchoServerHandler ¾cÖM¼¼åQŒä¹Ÿéƒ½ç‘ô承了(ji¨£n) ChannelInboundByteHandlerAdapter 。ä¸åŒåœ¨äºŽé‡å†™äº†(ji¨£n) channelActive() æ–ÒŽ(gu¨©)³•ã€?/span>
1 public class EchoClient { 2 3 private final String host; 4 private final int port; 5 private final int firstMessageSize; 6 7 public EchoClient(String host, int port, int firstMessageSize) { 8 this .host = host; 9 this .port = port;10 this .firstMessageSize = firstMessageSize;11 }12 13 public void run() throws Exception {14 // Configure the client. 15 Bootstrap b = new Bootstrap();16 try {17 b.group(new NioEventLoopGroup())18 .channel(NioSocketChannel.class )19 .option(ChannelOption.TCP_NODELAY, true )20 .remoteAddress(new InetSocketAddress(host, port))21 .handler(new ChannelInitializer<SocketChannel>() {22 @Override23 public void initChannel(SocketChannel ch) throws Exception {24 ch.pipeline().addLast(25 new LoggingHandler(LogLevel.INFO),26 new EchoClientHandler(firstMessageSize));27 }28 });29 30 // Start the client. 31 ChannelFuture f = b.connect().sync();32 33 // Wait until the connection is closed. 34 f.channel().closeFuture().sync();35 } finally {36 // Shut down the event loop to terminate all threads. 37 b.shutdown();38 }39 }40 41 public static void main(String[] args) throws Exception {42 // Print usage if no argument is specified. 43 if (args.length < 2 || args.length > 3) {44 System.err.println(45 "Usage: " + EchoClient.class .getSimpleName() +46 " <host> <port> [<first message size>]");47 return ;48 }49 50 // Parse options. 51 final String host = args[0];52 final int port = Integer.parseInt(args[1]);53 final int firstMessageSize;54 if (args.length == 3) {55 firstMessageSize = Integer.parseInt(args[2]);56 } else {57 firstMessageSize = 256;58 }59 60 new EchoClient(host, port, firstMessageSize).run();61 }62 }
Line 20: 指定˜qœç¨‹æœåŠ¡å™¨çš„åœ°å€å’Œç«¯å£ï¼ˆ localhost:8080 åQ?br />
备注:å› äØ“(f¨´)½W”者开始写Nettyæºç 分æžçš„æ—¶å€™ï¼ŒNetty 4.0˜q˜æ˜¯å¤„于Alpha阶段åQŒä¹‹åŽçš„APIå¯èƒ½˜q˜ä(sh¨´)¼š(x¨¬)有改动,½W”者将ä¼?x¨¬)å?qi¨¢ng)æ—¶æ›´æ”V€‚ä‹É用开æºå·²¾læœ‰å¥½å‡ òq´çš„æ—‰™—´äº?ji¨£n),一直没有时间和¾_‘ÖŠ›æ¥å…·ä½“ç ”½I¶æŸä¸ªå¼€æºé¡¹ç›®çš„具体实现åQŒè¿™‹Æ¡æ˜¯½W¬ä¸€‹Æ¡å†™å¼€æºé¡¹ç›®çš„æºç 分æžåQŒå¦‚æžœæ–‡ä¸æœ‰é”™è¯¯çš„地方,‹Æ¢è¿Žè¯»è€…å¯ä»¥ç•™a€æŒ‡å‡ºã€‚对于è{载的读者,è¯äh³¨æ˜Žæ–‡ç« 的出处ã€?/div>
希望和广大的开å‘è€?å¼€æºçˆ±å¥½è€…进行交‹¹ï¼Œ‹Æ¢è¿Žå¤§å®¶çš„ç•™a€å’Œè®¨è®ºã€?/div>
]]>
Netty 4.0 æºç 分æžåQˆä¸€åQ‰ï¼š(x¨¬)é…置环境 http://www.aygfsteel.com/czihong/articles/391784.htmlChan Chen Chan Chen Thu, 22 Nov 2012 13:21:00 GMT http://www.aygfsteel.com/czihong/articles/391784.html http://www.aygfsteel.com/czihong/comments/391784.html http://www.aygfsteel.com/czihong/articles/391784.html#Feedback 0 http://www.aygfsteel.com/czihong/comments/commentRss/391784.html http://www.aygfsteel.com/czihong/services/trackbacks/391784.html Netty æºç 分æžåQˆä¸€åQ‰ï¼š(x¨¬)é…置环境 1. 下è²jdk + elipse + egit 2. 相关jar包下è½?br />3. cynwin + telnet/ssh (setup.exe keywork:inetutils / ssh ) 3. 从example包开始阅è¯?br />