随笔-95  评论-31  文章-10  trackbacks-0
netty官方网站5.0.0版本处于开发起步阶段,所以稳定版本还基于4.0.19.Final,于是乎netty换为4.0.19

参考官方文档4.x和5.x
http://netty.io/wiki/user-guide-for-5.x.html
http://netty.io/wiki/user-guide-for-4.x.html
一上来给的例子就是什么Discard协议,它的含义:我看大多数直译“抛弃协议”,这话看的人不明不白,详细看了例子才知道,所谓抛弃协议,就是说我只接收消息,而不发送应答消息,但实际开发中,我们往往是需要客户端和服务端来回应答的,所以官方下文又给出Echo协议,echo英文含义:反射,回复等,也即该协议为有应答的。明白这两点,官方的例子也就很好理解了。

基于Discard协议,官方说明如下
1.DiscardServerHandler extends ChannelInboundHandlerAdapter, which is an implementation of ChannelInboundHandler. ChannelInboundHandler provides various event handler methods that you can override. For now, it is just enough to extend ChannelInboundHandlerAdapter rather than to implement the handler interface by yourself.

要表达的意思就是:我们一般情况下只需继承ChannelInboundHandlerAdapter即可,而不需要你自己去实现ChannelInboundHandler接口,该接口有一个适配器ChannelHandlerAdapter,而ChannelInboundHandlerAdapter又再次继承封装该适配器,等于就是官方替开发者写好的一个可用类,直接继承使用即可。
说明:该类在4.x版本中,官方又提供了一个SimpleChannelInboundHandler类提供了范型支持,也即可传输对象,它继承自ChannelInboundHandlerAdapter,等于又是对ChannelInboundHandlerAdapter的再次增强,使开发者不必每次,手动调用ByteBuf.release()方法,也即避免了如下这种形势

1 @Override
2 public void channelRead(ChannelHandlerContext ctx, Object msg) {
3     try {
4         // Do something with msg
5     } finally {
6         ReferenceCountUtil.release(msg);
7     }
8 }

只需关注里面的channelRead0()方法即可,但这个方法名字一看就命名不好,在5.x中已经修改为messageReceivered(),如果你想只关注接收到的消息,而不需要进行应答,那么你可以采取继承SimpleChannelInboundHandler<T>该类的方式,只需关注channelRead0()方法即可

2.We override the channelRead() event handler method here. This method is called with the received message, whenever new data is received from a client. In this example, the type of the received message is ByteBuf.

3.To implement the DISCARD protocol, the handler has to ignore the received message. ByteBuf is a reference-counted object which has to be released explicitly via the release() method. Please keep in mind that it is the handler's responsibility to release any reference-counted object passed to the handler. Usually, channelRead() handler method is implemented like the following:上图所示


4.The exceptionCaught() event handler method is called with a Throwable when an exception was raised by Netty due to an I/O error or by a handler implementation due to the exception thrown while processing events. In most cases, the caught exception should be logged and its associated channel should be closed here, although the implementation of this method can be different depending on what you want to do to deal with an exceptional situation. For example, you might want to send a response message with an error code before closing the connection.


上面2,3,4说的是传递的对象为ByteBuf,接收到消息后需转换为ByteBuf,同时释放release,如果该DiscardServerHandler继承自SimpleChannelInboundHandler<Object>,那么下面的channelRead方法换为channelRead0即可,并且无需再次调用release方法,只需对转换后的ByteBuf进行你想要的操作即可。同时对异常进行了封装,可根据需要重新定制异常方式
如下所示:
 1 public class DiscardServerHandler extends ChannelInboundHandlerAdapter { // (1)
 2 
 3     @Override
 4     public void channelRead(ChannelHandlerContext ctx, Object msg) { // (2)
 5         // Discard the received data silently.
 6         ((ByteBuf) msg).release(); // (3)
 7     }
 8 
 9     @Override
10     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // (4)
11         // Close the connection when an exception is raised.
12         cause.printStackTrace();
13         ctx.close();
14     }
15 }


上面说的都是“抛弃协议”的写法,如果需要应答的话,那么还是继承ChannelInboundHandlerAdapter类,在channelRead方法里面,下面是自己写的示例:
 1     @Override
 2     public void channelRead(ChannelHandlerContext ctx, Object msg)
 3             throws Exception {
 4             ByteBuf buff = (ByteBuf) msg;
 5             logger.info("\n该buff的容量字节数:"+buff.capacity()+
 6                     "\n该buff是否有可读数据:"+buff.isReadable()+
 7                     "\n该buff最大允许容量:"+buff.maxCapacity()+
 8                     "\n该buff最大允许可写空间:"+buff.maxWritableBytes()+
 9                     "\n该buff的可写空间:"+buff.writableBytes()+
10                     "\n该buff的可读空间:"+buff.readableBytes());
11         try {
12 
13             byte[] bytes = new byte[buff.readableBytes()];
14             buff.readBytes(bytes);
15             String str = new String(bytes);
16             logger.info("info ==" + str);
17             
18             String response = "Hi I'am server this is my info @" + str + "@";
19             
20             buff.writeBytes(response.getBytes());
21             ctx.writeAndFlush(buff);
22 //            buff = buff.retain();
23 //            buffResponse.release();
24         } finally {
25 //            ReferenceCountUtil.release(buff);
26         }
27     }

这样上节所说的问题就不复存在,客户端即可收到服务端发送的应答。
客户端代码改为
 1     public static void main(String[] args) throws UnknownHostException,IOException, InterruptedException {
 2         Socket socket = new Socket();
 3         InetSocketAddress endPoint = new InetSocketAddress("127.0.0.1",5442);
 4         socket.connect(endPoint);
 5         BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
 6         BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
 7         
 8         
 9         bw.write("hello world!");
10         bw.flush();
11         
12         Thread.sleep(1000);
13         InputStream is = socket.getInputStream();
14         while(is.available()>0){
15             byte[] bytes = new byte[126];
16             is.read(bytes);
17             
18             String str = new String(bytes);
19             System.out.println(str);
20         }

未完。。。。。。待续
posted on 2014-05-05 15:17 朔望魔刃 阅读(2269) 评论(0)  编辑  收藏 所属分类: netty

只有注册用户登录后才能发表评论。


网站导航: