转载Java NIO框架Netty简单使用 (http://blog.csdn.net/anxpp)

转载请注明出处:http://blog.csdn.net/anxpp/article/details/52108238,谢谢!

    之前写了一篇文章:Java 网络IO编程总结(BIO、NIO、AIO均含完整实例代码),介绍了如何使用Java原生IO支持进行网络编程,本文介绍一种更为简单的方式,即Java NIO框架。

    Netty是业界最流行的NIO框架之一,具有良好的健壮性、功能、性能、可定制性和可扩展性。同时,它提供的十分简单的API,大大简化了我们的网络编程。

    同Java IO介绍的文章一样,本文所展示的例子,实现了一个相同的功能。

1、服务端

    Server:

 

  1. package com.anxpp.io.calculator.netty;  
  2. import io.netty.bootstrap.ServerBootstrap;  
  3. import io.netty.channel.ChannelFuture;  
  4. import io.netty.channel.ChannelInitializer;  
  5. import io.netty.channel.ChannelOption;  
  6. import io.netty.channel.EventLoopGroup;  
  7. import io.netty.channel.nio.NioEventLoopGroup;  
  8. import io.netty.channel.socket.SocketChannel;  
  9. import io.netty.channel.socket.nio.NioServerSocketChannel;  
  10. public class Server {  
  11.     private int port;  
  12.     public Server(int port) {  
  13.         this.port = port;  
  14.     }  
  15.     public void run() throws Exception {  
  16.         EventLoopGroup bossGroup = new NioEventLoopGroup();  
  17.         EventLoopGroup workerGroup = new NioEventLoopGroup();  
  18.         try {  
  19.             ServerBootstrap b = new ServerBootstrap();  
  20.             b.group(bossGroup, workerGroup)  
  21.              .channel(NioServerSocketChannel.class)  
  22.              .option(ChannelOption.SO_BACKLOG, 1024)  
  23.              .childOption(ChannelOption.SO_KEEPALIVE, true)  
  24.              .childHandler(new ChannelInitializer<SocketChannel>() {  
  25.                  @Override  
  26.                  public void initChannel(SocketChannel ch) throws Exception {  
  27.                      ch.pipeline().addLast(new ServerHandler());  
  28.                  }  
  29.              });  
  30.             ChannelFuture f = b.bind(port).sync();  
  31.             System.out.println("服务器开启:"+port);  
  32.             f.channel().closeFuture().sync();  
  33.         } finally {  
  34.             workerGroup.shutdownGracefully();  
  35.             bossGroup.shutdownGracefully();  
  36.         }  
  37.     }  
  38.     public static void main(String[] args) throws Exception {  
  39.         int port;  
  40.         if (args.length > 0) {  
  41.             port = Integer.parseInt(args[0]);  
  42.         } else {  
  43.             port = 9090;  
  44.         }  
  45.         new Server(port).run();  
  46.     }  
  47. }  

    ServerHandler:

 

  1. package com.anxpp.io.calculator.netty;  
  2. import io.netty.buffer.ByteBuf;  
  3. import io.netty.buffer.Unpooled;  
  4. import io.netty.channel.ChannelHandlerContext;  
  5. import io.netty.channel.ChannelInboundHandlerAdapter;  
  6. import java.io.UnsupportedEncodingException;  
  7. import com.anxpp.io.utils.Calculator;  
  8. public class ServerHandler extends ChannelInboundHandlerAdapter {  
  9.     @Override  
  10.     public void channelRead(ChannelHandlerContext ctx, Object msg) throws UnsupportedEncodingException {  
  11.         ByteBuf in = (ByteBuf) msg;  
  12.         byte[] req = new byte[in.readableBytes()];  
  13.         in.readBytes(req);  
  14.         String body = new String(req,"utf-8");  
  15.         System.out.println("收到客户端消息:"+body);  
  16.         String calrResult = null;  
  17.         try{  
  18.             calrResult = Calculator.Instance.cal(body).toString();  
  19.         }catch(Exception e){  
  20.             calrResult = "错误的表达式:" + e.getMessage();  
  21.         }  
  22.         ctx.write(Unpooled.copiedBuffer(calrResult.getBytes()));  
  23.     }  
  24.     @Override  
  25.     public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {  
  26.         ctx.flush();  
  27.     }  
  28.     /** 
  29.      * 异常处理 
  30.      */  
  31.     @Override  
  32.     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {  
  33.         cause.printStackTrace();  
  34.         ctx.close();  
  35.     }  
  36. }  

2、客户端

    Client:

 

  1. package com.anxpp.io.calculator.netty;  
  2. import io.netty.bootstrap.Bootstrap;  
  3. import io.netty.channel.ChannelFuture;  
  4. import io.netty.channel.ChannelInitializer;  
  5. import io.netty.channel.ChannelOption;  
  6. import io.netty.channel.EventLoopGroup;  
  7. import io.netty.channel.nio.NioEventLoopGroup;  
  8. import io.netty.channel.socket.SocketChannel;  
  9. import io.netty.channel.socket.nio.NioSocketChannel;  
  10. import java.util.Scanner;  
  11. public class Client implements Runnable{  
  12.     static ClientHandler client = new ClientHandler();  
  13.     public static void main(String[] args) throws Exception {  
  14.         new Thread(new Client()).start();  
  15.         @SuppressWarnings("resource")  
  16.         Scanner scanner = new Scanner(System.in);  
  17.         while(client.sendMsg(scanner.nextLine()));  
  18.     }  
  19.     @Override  
  20.     public void run() {  
  21.         String host = "127.0.0.1";  
  22.         int port = 9090;  
  23.         EventLoopGroup workerGroup = new NioEventLoopGroup();  
  24.         try {  
  25.             Bootstrap b = new Bootstrap();  
  26.             b.group(workerGroup);  
  27.             b.channel(NioSocketChannel.class);  
  28.             b.option(ChannelOption.SO_KEEPALIVE, true);  
  29.             b.handler(new ChannelInitializer<SocketChannel>() {  
  30.                 @Override  
  31.                 public void initChannel(SocketChannel ch) throws Exception {  
  32.                     ch.pipeline().addLast(client);  
  33.                 }  
  34.             });  
  35.             ChannelFuture f = b.connect(host, port).sync();  
  36.             f.channel().closeFuture().sync();  
  37.         } catch (InterruptedException e) {  
  38.             e.printStackTrace();  
  39.         } finally {  
  40.             workerGroup.shutdownGracefully();  
  41.         }  
  42.     }  
  43. }  

    ClientHandler:

 

  1. package com.anxpp.io.calculator.netty;  
  2. import io.netty.buffer.ByteBuf;  
  3. import io.netty.buffer.Unpooled;  
  4. import io.netty.channel.ChannelHandlerContext;  
  5. import io.netty.channel.ChannelInboundHandlerAdapter;  
  6. import java.io.UnsupportedEncodingException;  
  7. public class ClientHandler extends ChannelInboundHandlerAdapter {  
  8.     ChannelHandlerContext ctx;  
  9.     /** 
  10.      * tcp链路简历成功后调用 
  11.      */  
  12.     @Override  
  13.     public void channelActive(ChannelHandlerContext ctx) throws Exception {  
  14.         this.ctx = ctx;  
  15.     }  
  16.     public boolean sendMsg(String msg){  
  17.         System.out.println("客户端发送消息:"+msg);  
  18.         byte[] req = msg.getBytes();  
  19.         ByteBuf m = Unpooled.buffer(req.length);  
  20.         m.writeBytes(req);  
  21.         ctx.writeAndFlush(m);  
  22.         return msg.equals("q")?false:true;  
  23.     }  
  24.     /** 
  25.      * 收到服务器消息后调用 
  26.      * @throws UnsupportedEncodingException  
  27.      */  
  28.     @Override  
  29.     public void channelRead(ChannelHandlerContext ctx, Object msg) throws UnsupportedEncodingException {  
  30.         ByteBuf buf = (ByteBuf) msg;  
  31.         byte[] req = new byte[buf.readableBytes()];  
  32.         buf.readBytes(req);  
  33.         String body = new String(req,"utf-8");  
  34.         System.out.println("服务器消息:"+body);  
  35.     }  
  36.     /** 
  37.      * 发生异常时调用 
  38.      */  
  39.     @Override  
  40.     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {  
  41.         cause.printStackTrace();  
  42.         ctx.close();  
  43.     }  
  44. }  

3、用于计算的工具类

  1. package com.anxpp.io.utils;
  2. import javax.script.ScriptEngine;
  3. import javax.script.ScriptEngineManager;
  4. import javax.script.ScriptException;
  5. public enum Calculator {
  6. Instance;
  7. private final static ScriptEngine jse = new ScriptEngineManager().getEngineByName("JavaScript");
  8. public Object cal(String expression) throws ScriptException{
  9. return jse.eval(expression);
  10. }
  11. }

4、测试

    分别启动服务端和客户端,然后再客户端控制台输入表达式:

  1. 1+5+5+5+5+5
  2. 客户端发送消息:1+5+5+5+5+5
  3. 服务器消息:26
  4. 156158*458918+125615
  5. 客户端发送消息:156158*458918+125615
  6. 服务器消息:7.1663842659E10
  7. 1895612+555+5+5+5+5+5+5+5-5*4/4
  8. 客户端发送消息:1895612+555+5+5+5+5+5+5+5-5*4/4
  9. 服务器消息:1896197

    可以看到服务端返回的结果。

    查看服务端控制台:

  1. 服务器开启:9090
  2. 收到客户端消息:1+5+5+5+5+5
  3. 收到客户端消息:156158*458918+125615
  4. 收到客户端消息:1895612+555+5+5+5+5+5+5+5-5*4/4

posted on 2018-01-31 15:24  铭--为将来  阅读(298)  评论(0编辑  收藏  举报