一起学Netty(一)

来源:互联网 发布:mac下提取dsdt命令 编辑:程序博客网 时间:2024/05/21 22:57
 

一起学Netty(一)之 Hello Netty



 


maven的依赖,我们如下:

[html] view plain copy
  1. <dependencies>  
  2.     <dependency>  
  3.       <groupId>junit</groupId>  
  4.       <artifactId>junit</artifactId>  
  5.       <version>4.10</version>  
  6.       <scope>test</scope>  
  7.     </dependency>  
  8.     <dependency>  
  9.     <groupId>io.netty</groupId>  
  10.     <artifactId>netty-all</artifactId>  
  11.     <version>4.0.21.Final</version>  
  12.      </dependency>  
  13.   </dependencies>  



我们先写Netty器端的ChannelHandler,我们命名Netty的服务端的处理器为:HelloWorldServerHandler,继承于ChannelInboundHandlerAdapter,《Netty in Action》中介绍过,我们不需要使每一个inboundChannel继承于ChannelInboundHandler,这样会需要我们实现ChannelInboundHandler中的所有接口,在一般的channel中我们没有必要这样做,这样只会增加我们的额外的工作量,我们只需要继承ChannelInboundHandlerAdapter,继承它的适配就可以了,我们需要实现几个特别重要的方法,例如读取的方法channelRead和异常处理的方法exceptionCaught,源码如下:

[java] view plain copy
  1. package com.lyncc.netty.hello;  
  2.   
  3. import io.netty.channel.ChannelHandlerContext;  
  4. import io.netty.channel.ChannelInboundHandlerAdapter;  
  5.   
  6. public class HelloWorldServerHandler extends ChannelInboundHandlerAdapter{  
  7.       
  8.       
  9.     @Override  
  10.     public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {  
  11.         System.out.println("server channelRead..");  
  12.         System.out.println(ctx.channel().remoteAddress()+"->Server :"+ msg.toString());  
  13.         ctx.write("server write"+msg);  
  14.         ctx.flush();  
  15.     }  
  16.       
  17.     @Override  
  18.     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {  
  19.         cause.printStackTrace();  
  20.         ctx.close();  
  21.     }  
  22.   
  23. }  

接下来我们就要写Netty的服务器端了,书中写的很清楚,我们需要写一个ServerBootstrap,ServerBootstrap的写法是现在比较流行的流式编程法,我们需要指定它的transports,是NIO还是OIO,还需要指定端口号,最最重要的是安装server端的处理器,也就是我们之前写的HelloWorldServerHandler,还有一些Option的配置,这里只是用到,以后我们一起分析这些Option的作用,写server端还有一点需要注意,就是需要关闭连接,释放线程资源,源码如下:

[java] view plain copy
  1. package com.lyncc.netty.hello;  
  2.   
  3. import io.netty.bootstrap.ServerBootstrap;  
  4. import io.netty.channel.ChannelFuture;  
  5. import io.netty.channel.ChannelInitializer;  
  6. import io.netty.channel.ChannelOption;  
  7. import io.netty.channel.EventLoopGroup;  
  8. import io.netty.channel.nio.NioEventLoopGroup;  
  9. import io.netty.channel.socket.SocketChannel;  
  10. import io.netty.channel.socket.nio.NioServerSocketChannel;  
  11. import io.netty.handler.codec.string.StringDecoder;  
  12. import io.netty.handler.codec.string.StringEncoder;  
  13.   
  14. import java.net.InetSocketAddress;  
  15.   
  16. public class HelloWorldServer {  
  17.   
  18.     private int port;  
  19.       
  20.     public HelloWorldServer(int port) {  
  21.         this.port = port;  
  22.     }  
  23.       
  24.     public void start(){  
  25.         EventLoopGroup bossGroup = new NioEventLoopGroup(1);  
  26.         EventLoopGroup workerGroup = new NioEventLoopGroup();  
  27.         try {  
  28.             ServerBootstrap sbs = new ServerBootstrap().group(bossGroup,workerGroup).channel(NioServerSocketChannel.class).localAddress(new InetSocketAddress(port))  
  29.                     .childHandler(new ChannelInitializer<SocketChannel>() {  
  30.                           
  31.                         protected void initChannel(SocketChannel ch) throws Exception {  
  32. //                            ch.pipeline().addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));  
  33.                             ch.pipeline().addLast("decoder"new StringDecoder());  
  34.                             ch.pipeline().addLast("encoder"new StringEncoder());  
  35.                             ch.pipeline().addLast(new HelloWorldServerHandler());  
  36.                         };  
  37.                           
  38.                     }).option(ChannelOption.SO_BACKLOG, 128)     
  39.                     .childOption(ChannelOption.SO_KEEPALIVE, true);  
  40.              // 绑定端口,开始接收进来的连接  
  41.              ChannelFuture future = sbs.bind(port).sync();    
  42.                
  43.              System.out.println("Server start listen at " + port );  
  44.              future.channel().closeFuture().sync();  
  45.         } catch (Exception e) {  
  46.             bossGroup.shutdownGracefully();  
  47.             workerGroup.shutdownGracefully();  
  48.         }  
  49.     }  
  50.       
  51.     public static void main(String[] args) throws Exception {  
  52.         int port;  
  53.         if (args.length > 0) {  
  54.             port = Integer.parseInt(args[0]);  
  55.         } else {  
  56.             port = 8080;  
  57.         }  
  58.         new HelloWorldServer(port).start();  
  59.     }  
  60. }  
如法炮制,客户端的handler,我们依旧命名为HelloWorldClientHandler,也是继承于ChannelInboundHandlerAdapter

[java] view plain copy
  1. package com.lyncc.netty.hello;  
  2.   
  3. import io.netty.channel.ChannelHandlerContext;  
  4. import io.netty.channel.ChannelInboundHandlerAdapter;  
  5.   
  6. public class HelloWorldClientHandler extends ChannelInboundHandlerAdapter{  
  7.       
  8.     
  9.       @Override  
  10.       public void channelActive(ChannelHandlerContext ctx) {  
  11.           System.out.println("HelloWorldClientHandler Active");  
  12.       }  
  13.     
  14.       @Override  
  15.       public void channelRead(ChannelHandlerContext ctx, Object msg) {  
  16.          System.out.println("HelloWorldClientHandler read Message:"+msg);  
  17.       }  
  18.     
  19.     
  20.      @Override  
  21.      public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {  
  22.          cause.printStackTrace();  
  23.          ctx.close();  
  24.       }  
  25.   
  26. }  
客户端我们需要写一个Bootstrap,也需要指定客户端的处理器,我们这里在客户端和服务器端都加了编码和解码两个String类型的译码器,这样的例子也算比较完整的hello world的例子了,完整的代码如下:

[java] view plain copy
  1. package com.lyncc.netty.hello;  
  2.   
  3. import io.netty.bootstrap.Bootstrap;  
  4. import io.netty.channel.ChannelFuture;  
  5. import io.netty.channel.ChannelInitializer;  
  6. import io.netty.channel.ChannelOption;  
  7. import io.netty.channel.ChannelPipeline;  
  8. import io.netty.channel.EventLoopGroup;  
  9. import io.netty.channel.nio.NioEventLoopGroup;  
  10. import io.netty.channel.socket.SocketChannel;  
  11. import io.netty.channel.socket.nio.NioSocketChannel;  
  12. import io.netty.handler.codec.string.StringDecoder;  
  13. import io.netty.handler.codec.string.StringEncoder;  
  14.   
  15. public class HelloWorldClient {  
  16.       
  17.     static final String HOST = System.getProperty("host""127.0.0.1");  
  18.     static final int PORT = Integer.parseInt(System.getProperty("port""8080"));  
  19.     static final int SIZE = Integer.parseInt(System.getProperty("size""256"));  
  20.   
  21.     public static void main(String[] args) throws Exception {  
  22.   
  23.         // Configure the client.  
  24.         EventLoopGroup group = new NioEventLoopGroup();  
  25.         try {  
  26.             Bootstrap b = new Bootstrap();  
  27.             b.group(group)  
  28.              .channel(NioSocketChannel.class)  
  29.              .option(ChannelOption.TCP_NODELAY, true)  
  30.              .handler(new ChannelInitializer<SocketChannel>() {  
  31.                  @Override  
  32.                  public void initChannel(SocketChannel ch) throws Exception {  
  33.                      ChannelPipeline p = ch.pipeline();  
  34.                      p.addLast("decoder"new StringDecoder());  
  35.                      p.addLast("encoder"new StringEncoder());  
  36.                      p.addLast(new HelloWorldClientHandler());  
  37.                  }  
  38.              });  
  39.   
  40.             ChannelFuture future = b.connect(HOST, PORT).sync();  
  41.             future.channel().writeAndFlush("Hello Netty Server ,I am a common client");  
  42.             future.channel().closeFuture().sync();  
  43.         } finally {  
  44.             group.shutdownGracefully();  
  45.         }  
  46.     }  
  47.   
  48. }  
我们打开HelloWorldServer的代码,运行main函数,eclipse的控制台打印信息如下:

说明服务器已经成功运行,在8080端口监听了

我们再打开HelloWorldClient代码,同样运行main函数。控制台打印信息如下:

第一行是HelloWorldClientHandler该处理器的channelActive的方法打印的输出,第二行是channelRead方法的输出,这个输出是服务器端写入的,返回给客户端的


我们再回头看服务器端,此时服务器的HelloWorldServerHandler的channelRead的方法应该打印从客户端收到的信息了


好了,到此为止,Netty的服务器端和客户端就完全搭建完毕了,我们做到了客户端发送信息,服务器端接收且把收到的信息原样返回给客户端了

阅读全文
0 0
原创粉丝点击