Netty学习:搭建一个简单的Netty服务

Netty 是一个基于 JAVA NIO 类库的异步通信框架,它的架构特点是:异步非阻塞、基于事件驱动、高性能、高可靠性和高可定制性。换句话说,Netty是一个NIO框架,使用它可以简单快速地开发网络应用程序,比如客户端和服务端的协议。Netty大大简化了网络程序的开发过程比如TCP和UDP的 Socket的开发。Netty 已逐渐成为 Java NIO 编程的首选框架。

项目官方地址:http://netty.io/index.html

一. Netty 的优点:

  • API 使用简单,开发门槛低;

  • 功能强大,预置了多种编解码功能,支持多种主流协议;

  • 定制能力强,可以通过 ChannelHandler 对通信框架进行灵活的扩展;

  • 性能高,通过与其它业界主流的 NIO 框架对比,Netty 的综合性能最优;

  • 社区活跃,版本迭代周期短,发现的 BUG 可以被及时修复,同时,更多的新功能会被加入;

  • 经历了大规模的商业应用考验,质量得到验证。在互联网、大数据、网络游戏、企业应用、电信软件等众多行业得到成功商用,证明了它完全满足不同行业的商用标准。

二. 搭建Netty服务:

  1. 添加pom依赖

    Pom代码  

     

    1.   

    2.     io.netty  

    3.     netty-all  

    4.     4.1.0.Final  

    5.   

  2. SimpleServer(服务端)

    Java代码  

     

    1. package com.yingjun.netty.server;  

    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.   

    12. /** 

    13.  *  

    14.  * Netty中,通讯的双方建立连接后,会把数据按照ByteBuf的方式进行传输, 

    15.  * 例如http协议中,就是通过HttpRequestDecoder对ByteBuf数据流进行处理,转换成http的对象。 

    16.  *  

    17.  */  

    18. public class SimpleServer {  

    19.     private int port;  

    20.   

    21.     public SimpleServer(int port) {  

    22.         this.port = port;  

    23.     }  

    24.   

    25.     public void run() throws Exception {  

    26.         //EventLoopGroup是用来处理IO操作的多线程事件循环器  

    27.         //bossGroup 用来接收进来的连接  

    28.         EventLoopGroup bossGroup = new NioEventLoopGroup();   

    29.         //workerGroup 用来处理已经被接收的连接  

    30.         EventLoopGroup workerGroup = new NioEventLoopGroup();  

    31.         try {  

    32.             //启动 NIO 服务的辅助启动类  

    33.             ServerBootstrap b = new ServerBootstrap();   

    34.             b.group(bossGroup, workerGroup)  

    35.                 //配置 Channel  

    36.                 .channel(NioServerSocketChannel.class)  

    37.                 .childHandler(new ChannelInitializer() {   

    38.                         @Override  

    39.                         public void initChannel(SocketChannel ch) throws Exception {  

    40.                             // 注册handler    

    41.                             ch.pipeline().addLast(new SimpleServerHandler());  

    42.                         }  

    43.                     })  

    44.                 .option(ChannelOption.SO_BACKLOG, 128)   

    45.                 .childOption(ChannelOption.SO_KEEPALIVE, true);   

    46.   

    47.             // 绑定端口,开始接收进来的连接  

    48.             ChannelFuture f = b.bind(port).sync();  

    49.             // 等待服务器 socket 关闭 。  

    50.             f.channel().closeFuture().sync();  

    51.         } finally {  

    52.             workerGroup.shutdownGracefully();  

    53.             bossGroup.shutdownGracefully();  

    54.         }  

    55.     }  

    56.       

    57.     public static void main(String[] args) throws Exception {  

    58.         new SimpleServer(9999).run();  

    59.     }  

    60. }  

  3. SimpleServerHandler(服务端请求处理Handler)

    Java代码  

     

    1. package com.yingjun.netty.server;  

    2.   

    3. import io.netty.buffer.ByteBuf;  

    4. import io.netty.channel.ChannelHandlerContext;  

    5. import io.netty.channel.ChannelInboundHandlerAdapter;  

    6.   

    7. public class SimpleServerHandler extends ChannelInboundHandlerAdapter {  

    8.   

    9.     @Override  

    10.     public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {  

    11.         System.out.println("SimpleServerHandler.channelRead");  

    12.         ByteBuf result = (ByteBuf) msg;  

    13.         byte[] result1 = new byte[result.readableBytes()];  

    14.         // msg中存储的是ByteBuf类型的数据,把数据读取到byte[]中  

    15.         result.readBytes(result1);  

    16.         String resultStr = new String(result1);  

    17.         // 接收并打印客户端的信息  

    18.         System.out.println("Client said:" + resultStr);  

    19.         // 释放资源,这行很关键  

    20.         result.release();  

    21.   

    22.         // 向客户端发送消息  

    23.         String response = "hello client!";  

    24.         // 在当前场景下,发送的数据必须转换成ByteBuf数组  

    25.         ByteBuf encoded = ctx.alloc().buffer(4 * response.length());  

    26.         encoded.writeBytes(response.getBytes());  

    27.         ctx.write(encoded);  

    28.         ctx.flush();  

    29.     }  

    30.   

    31.     @Override  

    32.     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {  

    33.         // 当出现异常就关闭连接  

    34.         cause.printStackTrace();  

    35.         ctx.close();  

    36.     }  

    37.   

    38.     @Override  

    39.     public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {  

    40.         ctx.flush();  

    41.     }  

    42.   

    43. }  

  4. SimpleServer(客户端)

    Java代码  

     

    1. package com.yingjun.netty.server;  

    2.   

    3. import io.netty.bootstrap.Bootstrap;  

    4. import io.netty.bootstrap.ServerBootstrap;  

    5. import io.netty.channel.ChannelFuture;  

    6. import io.netty.channel.ChannelInitializer;  

    7. import io.netty.channel.ChannelOption;  

    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.NioServerSocketChannel;  

    12. import io.netty.channel.socket.nio.NioSocketChannel;  

    13.   

    14. public class SimpleClient {  

    15.       

    16.     public void connect(String host, int port) throws Exception {  

    17.         EventLoopGroup workerGroup = new NioEventLoopGroup();  

    18.   

    19.         try {  

    20.             Bootstrap b = new Bootstrap();  

    21.             b.group(workerGroup);  

    22.             b.channel(NioSocketChannel.class);  

    23.             b.option(ChannelOption.SO_KEEPALIVE, true);  

    24.             b.handler(new ChannelInitializer() {  

    25.                 @Override  

    26.                 public void initChannel(SocketChannel ch) throws Exception {  

    27.                     ch.pipeline().addLast(new SimpleClientHandler());  

    28.                 }  

    29.             });  

    30.   

    31.             // Start the client.  

    32.             ChannelFuture f = b.connect(host, port).sync();  

    33.   

    34.             // Wait until the connection is closed.  

    35.             f.channel().closeFuture().sync();  

    36.         } finally {  

    37.             workerGroup.shutdownGracefully();  

    38.         }  

    39.     }  

    40.       

    41.     public static void main(String[] args) throws Exception {  

    42.         SimpleClient client=new SimpleClient();  

    43.         client.connect("127.0.0.1"9999);  

    44.     }  

    45.       

    46. }  

  5. SimpleServerHandler(客户端请求处理Handler springmvc+mybatis+spring 整合 下载地址  

    Java代码  

     

    1. package com.yingjun.netty.server;  

    2.   

    3. import io.netty.buffer.ByteBuf;  

    4. import io.netty.channel.ChannelHandlerContext;  

    5. import io.netty.channel.ChannelInboundHandlerAdapter;  

    6.   

    7. public class SimpleClientHandler extends ChannelInboundHandlerAdapter {  

    8.   

    9.     @Override  

    10.     public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {  

    11.         System.out.println("SimpleClientHandler.channelRead");    

    12.         ByteBuf result = (ByteBuf) msg;    

    13.         byte[] result1 = new byte[result.readableBytes()];    

    14.         result.readBytes(result1);    

    15.         System.out.println("Server said:" + new String(result1));    

    16.         result.release();    

    17.     }  

    18.   

    19.     @Override  

    20.     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {  

    21.         // 当出现异常就关闭连接  

    22.         cause.printStackTrace();  

    23.         ctx.close();  

    24.     }  

    25.   

    26.       

    27.     // 连接成功后,向server发送消息    

    28.     @Override    

    29.     public void channelActive(ChannelHandlerContext ctx) throws Exception {    

    30.         String msg = "hello Server!";    

    31.         ByteBuf encoded = ctx.alloc().buffer(4 * msg.length());    

    32.         encoded.writeBytes(msg.getBytes());    

    33.         ctx.write(encoded);    

    34.         ctx.flush();    

    35.     }    

    36. }  

  6. 运行结果:

    Java代码  

     

    1. SimpleClientHandler.channelRead  

    2. Server said:hello client!  

    3. ------------------------------------------  

    4. SimpleServerHandler.channelRead  

    5. Client said:hello Server!  

    6. SimpleServerHandler.channelRead  

    7. Client said:hello Server!