netty初步

来源:互联网 发布:p衣服的软件 编辑:程序博客网 时间:2024/04/29 20:17

netty是java的高性能socket框架,linux下基epoll,这里不对他多牛逼作分析,网上资料很多,这里针对一般socket的业务作个例子

几个基本概念:

  channel类似于socket句柄的抽象
  pipeline是每个socket里面的eventHandler的处理响应链

每个socket(channel)绑定一个pipeline,,每个pipeline绑定若干个handler,netty里面的handler,专门用来处理和业务有关的东西,handler有upHandler和downHandler,down用来处理发包,up用来处理收包,大概的示例图看这里

注意上面的123的顺序,很重要,在netty里面,处理顺序如图,对于up类的收包处理,最靠近收包层的顺序越靠前;对于down类的包处理,最靠近收包层的顺序越靠后

还有一些encoder和decoder,encoder用来在发包之前进行加密,decoder在收包以后进行解码,然后业务数据跳到事件处理流程。

下面具体上代码,版本是netty3.6

MessageClientHandler.java

复制代码
 1 package com.netty.test.client; 2  3 import java.util.logging.Level; 4 import java.util.logging.Logger; 5  6 import org.jboss.netty.channel.ChannelHandlerContext; 7 import org.jboss.netty.channel.ChannelStateEvent; 8 import org.jboss.netty.channel.ExceptionEvent; 9 import org.jboss.netty.channel.MessageEvent;10 import org.jboss.netty.channel.SimpleChannelUpstreamHandler;11 12 public class MessageClientHandler extends SimpleChannelUpstreamHandler {13  14     private static final Logger logger = Logger.getLogger(15             MessageClientHandler.class.getName());16  17  18     @Override19     public void channelConnected(20             ChannelHandlerContext ctx, ChannelStateEvent e) {21         String message = "hello kafka0102";22         e.getChannel().write(message);23     }24  25     @Override26     public void messageReceived(27             ChannelHandlerContext ctx, MessageEvent e) {28         // Send back the received message to the remote peer.29         System.err.println("client messageReceived send message "+e.getMessage());30         try {31             Thread.sleep(1000*3);32         } catch (Exception ex) {33             ex.printStackTrace();34         }35         e.getChannel().write(e.getMessage());36     }37  38     @Override39     public void exceptionCaught(40             ChannelHandlerContext ctx, ExceptionEvent e) {41         // Close the connection when an exception is raised.42         logger.log(43                 Level.WARNING,44                 "Unexpected exception from downstream.",45                 e.getCause());46         e.getChannel().close();47     }48 }
复制代码

MessageDecoder.java

复制代码
 1 package com.netty.test.client; 2 import org.jboss.netty.buffer.ChannelBuffer; 3 import org.jboss.netty.channel.Channel; 4 import org.jboss.netty.channel.ChannelHandlerContext; 5 import org.jboss.netty.handler.codec.frame.FrameDecoder; 6  7 public class MessageDecoder extends FrameDecoder { 8   9     @Override10     protected Object decode(11             ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {12         if (buffer.readableBytes() < 4) {13             return null;//(1)14         }15         int dataLength = buffer.getInt(buffer.readerIndex());16         if (buffer.readableBytes() < dataLength + 4) {17             return null;//(2)18         }19  20         buffer.skipBytes(4);//(3)21         byte[] decoded = new byte[dataLength];22         buffer.readBytes(decoded);23         String msg = new String(decoded);//(4)24         return msg;25     }26 }
复制代码

MessageEncoder.java

复制代码
 1 package com.netty.test.client; 2 import org.jboss.netty.buffer.ChannelBuffer; 3 import org.jboss.netty.buffer.ChannelBuffers; 4 import org.jboss.netty.channel.Channel; 5 import org.jboss.netty.channel.ChannelHandlerContext; 6 import org.jboss.netty.handler.codec.oneone.OneToOneEncoder; 7  8 public class MessageEncoder extends OneToOneEncoder { 9  10     @Override11     protected Object encode(12             ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception {13         if (!(msg instanceof String)) {14             return msg;//(1)15         }16  17         String res = (String)msg;18         byte[] data = res.getBytes();19         int dataLength = data.length;20         ChannelBuffer buf = ChannelBuffers.dynamicBuffer();//(2)21         buf.writeInt(dataLength);22         buf.writeBytes(data);23         return buf;//(3)24     }25 }
复制代码

用来测试的TestClientDownHandlerA.java

复制代码
 1 package com.netty.test.client; 2  3 import org.jboss.netty.channel.ChannelEvent; 4 import org.jboss.netty.channel.ChannelHandlerContext; 5 import org.jboss.netty.channel.SimpleChannelDownstreamHandler; 6  7 public class TestClientDownHandlerA extends SimpleChannelDownstreamHandler { 8       9     public void handleDownstream(ChannelHandlerContext ctx, ChannelEvent e)10             throws Exception {11         System.err.println("test client Down handlerA ");12         13         super.handleDownstream(ctx, e);14     }15 }
复制代码

用来测试的TestClientDownHandlerB.java

复制代码
 1 package com.netty.test.client; 2  3 import org.jboss.netty.channel.ChannelEvent; 4 import org.jboss.netty.channel.ChannelHandlerContext; 5 import org.jboss.netty.channel.SimpleChannelDownstreamHandler; 6  7 public class TestClientDownHandlerB extends SimpleChannelDownstreamHandler { 8       9     public void handleDownstream(ChannelHandlerContext ctx, ChannelEvent e)10             throws Exception {11         System.err.println("test client Down handlerB ");12         13         super.handleDownstream(ctx, e);14     }15 }
复制代码

MessageClientPipelineFactory.java

复制代码
 1 package com.netty.test.client; 2  3 import org.jboss.netty.channel.ChannelPipeline; 4 import org.jboss.netty.channel.ChannelPipelineFactory; 5 import org.jboss.netty.channel.Channels; 6  7 import com.netty.test.client.MessageDecoder; 8 import com.netty.test.client.MessageEncoder; 9 10 public class MessageClientPipelineFactory implements ChannelPipelineFactory {11 12     public ChannelPipeline getPipeline() throws Exception {13         ChannelPipeline pipeline = Channels.pipeline();14         15         pipeline.addLast("decoder", new MessageDecoder());16         pipeline.addLast("encoder", new MessageEncoder());17         pipeline.addLast("handler", new MessageClientHandler());18 19         pipeline.addFirst("testClientDownHandlerA", new TestClientDownHandlerA());20         pipeline.addFirst("testClientDownHandlerB", new TestClientDownHandlerB());21         22         return pipeline;23     }24 }
复制代码

MessageClient.java

复制代码
 1 package com.netty.test.client; 2  3 import java.net.InetSocketAddress; 4 import java.util.concurrent.Executors; 5 import org.jboss.netty.bootstrap.ClientBootstrap; 6 import org.jboss.netty.channel.ChannelFuture; 7 import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory; 8  9 public class MessageClient {10  11     public static void main(String[] args) throws Exception {12         // Parse options.13         String host = "127.0.0.1";14         int port = 8888;15         // Configure the client.16         ClientBootstrap bootstrap = new ClientBootstrap(17                 new NioClientSocketChannelFactory(18                         Executors.newCachedThreadPool(),19                         Executors.newCachedThreadPool()));20         // Set up the event pipeline factory.21         bootstrap.setPipelineFactory(new MessageClientPipelineFactory());22         // Start the connection attempt.23         ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));24         // Wait until the connection is closed or the connection attempt fails.25         future.getChannel().getCloseFuture().awaitUninterruptibly();26         // Shut down thread pools to exit.27         bootstrap.releaseExternalResources();28     }29 }
复制代码

客户端代码完成

以下为服务端测试代码

MessageDecoder和Messagencoder照抄,这个都是一样的

MessageServerHandler.java

复制代码
 1 package com.netty.test.server; 2 import java.util.logging.Level; 3 import java.util.logging.Logger; 4  5 import org.jboss.netty.channel.ChannelHandlerContext; 6 import org.jboss.netty.channel.ExceptionEvent; 7 import org.jboss.netty.channel.MessageEvent; 8 import org.jboss.netty.channel.SimpleChannelUpstreamHandler; 9 10 public class MessageServerHandler extends SimpleChannelUpstreamHandler {11  12     private static final Logger logger = Logger.getLogger(13             MessageServerHandler.class.getName());14  15     @Override16     public void messageReceived(17             ChannelHandlerContext ctx, MessageEvent e) {18         if (!(e.getMessage() instanceof String)) {19             return;//(1)20         }21         String msg = (String) e.getMessage();22         System.err.println("got msg:"+msg);23         e.getChannel().write(msg);//(2)24     }25  26     @Override27     public void exceptionCaught(28             ChannelHandlerContext ctx, ExceptionEvent e) {29         logger.log(30                 Level.WARNING,31                 "Unexpected exception from downstream.",32                 e.getCause());33         e.getChannel().close();34     }35 }
复制代码

TestServerUpHandlerA.java

复制代码
 1 package com.netty.test.server; 2  3 import org.jboss.netty.channel.ChannelHandlerContext; 4 import org.jboss.netty.channel.ExceptionEvent; 5 import org.jboss.netty.channel.MessageEvent; 6 import org.jboss.netty.channel.SimpleChannelUpstreamHandler; 7  8 public class TestServerUpHandlerA extends SimpleChannelUpstreamHandler { 9      10     @Override11     public void messageReceived(12             ChannelHandlerContext ctx, MessageEvent e) {13         // Send back the received message to the remote peer.14         System.err.println("server test upHandlerA get message "+e.getMessage());15 16         try {17             super.messageReceived(ctx, e);18         } catch (Exception e1) {19             // TODO Auto-generated catch block20             e1.printStackTrace();21         }22     }23  24     @Override25     public void exceptionCaught(26             ChannelHandlerContext ctx, ExceptionEvent e) {27 28         e.getChannel().close();29     }30 }
复制代码

TestServerUpHandlerB.java

复制代码
 1 package com.netty.test.server; 2  3 import org.jboss.netty.channel.ChannelHandlerContext; 4 import org.jboss.netty.channel.ExceptionEvent; 5 import org.jboss.netty.channel.MessageEvent; 6 import org.jboss.netty.channel.SimpleChannelUpstreamHandler; 7  8 public class TestServerUpHandlerB extends SimpleChannelUpstreamHandler { 9      10     @Override11     public void messageReceived(12             ChannelHandlerContext ctx, MessageEvent e) {13         // Send back the received message to the remote peer.14         System.err.println("server test upHandlerB get message "+e.getMessage());15 16         try {17             super.messageReceived(ctx, e);18         } catch (Exception e1) {19             // TODO Auto-generated catch block20             e1.printStackTrace();21         }22     }23  24     @Override25     public void exceptionCaught(26             ChannelHandlerContext ctx, ExceptionEvent e) {27 28         e.getChannel().close();29     }30 }
复制代码

MessageServerPipelineFactory.java

复制代码
 1 package com.netty.test.server; 2  3 import org.jboss.netty.channel.ChannelPipeline; 4 import org.jboss.netty.channel.ChannelPipelineFactory; 5 import org.jboss.netty.channel.Channels; 6  7 public class MessageServerPipelineFactory implements 8         ChannelPipelineFactory { 9  10     public ChannelPipeline getPipeline() throws Exception {11         ChannelPipeline pipeline = Channels.pipeline();12  13         pipeline.addLast("decoder", new MessageDecoder());14         pipeline.addLast("encoder", new MessageEncoder());15         pipeline.addLast("handler", new MessageServerHandler());16         17 //        pipeline.addFirst("testServerUpHandlerA", new TestServerUpHandlerA());18 //        pipeline.addFirst("testServerUpHandlerB", new TestServerUpHandlerB());19         20         return pipeline;21     }22 }
复制代码

MessageServer.java

复制代码
 1 package com.netty.test.server; 2  3 import java.net.InetSocketAddress; 4 import java.util.concurrent.Executors; 5 import org.jboss.netty.bootstrap.ServerBootstrap; 6 import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; 7  8 public class MessageServer { 9  10     public static void main(String[] args) throws Exception {11         // Configure the server.12         ServerBootstrap bootstrap = new ServerBootstrap(13                 new NioServerSocketChannelFactory(14                         Executors.newCachedThreadPool(),15                         Executors.newCachedThreadPool()));16  17         // Set up the default event pipeline.18         bootstrap.setPipelineFactory(new MessageServerPipelineFactory());19  20         // Bind and start to accept incoming connections.21         bootstrap.bind(new InetSocketAddress(8888));22     }23 }
复制代码

通过测试,可以发现handler的处理顺序,和图上面的是一致的;还有可以参考下encoder和decoder的写法,改改,直接用于项目。

0 0
原创粉丝点击