Java NIO框架Netty使用案例
- 更新时间:2020-03-19 20:38:31
- 编辑:双千叶
之前写了一篇文章:Java 网络IO编程总结(BIO、NIO、AIO均含完整实例代码),介绍了如何使用Java原生IO支持进行网络编程,本文介绍一种更为简单的方式,即Java NIO框架。
Netty是业界最流行的NIO框架之一,具有良好的健壮性、功能、性能、可定制性和可扩展性。同时,它提供的十分简单的API,大大简化了我们的网络编程。
同Java IO介绍的文章一样,本文所展示的例子,实现了一个相同的功能。
1、服务端
Server:
package com.anxpp.io.calculator.netty; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; public class Server { private int port; public Server(int port) { this.port = port; } public void run() throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG, 1024) .childOption(ChannelOption.SO_KEEPALIVE, true) .childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new ServerHandler()); } }); ChannelFuture f = b.bind(port).sync(); System.out.println("服务器开启:"+port); f.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { int port; if (args.length > 0) { port = Integer.parseInt(args[0]); } else { port = 9090; } new Server(port).run(); } }
ServerHandler:
package com.anxpp.io.calculator.netty; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import java.io.UnsupportedEncodingException; import com.anxpp.io.utils.Calculator; public class ServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws UnsupportedEncodingException { ByteBuf in = (ByteBuf) msg; byte[] req = new byte[in.readableBytes()]; in.readBytes(req); String body = new String(req,"utf-8"); System.out.println("收到客户端消息:"+body); String calrResult = null; try{ calrResult = Calculator.Instance.cal(body).toString(); }catch(Exception e){ calrResult = "错误的表达式:" + e.getMessage(); } ctx.write(Unpooled.copiedBuffer(calrResult.getBytes())); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { ctx.flush(); } /** * 异常处理 */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } } package com.anxpp.io.calculator.netty; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import java.io.UnsupportedEncodingException; import com.anxpp.io.utils.Calculator; public class ServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws UnsupportedEncodingException { ByteBuf in = (ByteBuf) msg; byte[] req = new byte[in.readableBytes()]; in.readBytes(req); String body = new String(req,"utf-8"); System.out.println("收到客户端消息:"+body); String calrResult = null; try{ calrResult = Calculator.Instance.cal(body).toString(); }catch(Exception e){ calrResult = "错误的表达式:" + e.getMessage(); } ctx.write(Unpooled.copiedBuffer(calrResult.getBytes())); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { ctx.flush(); } /** * 异常处理 */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } }
2、客户端
Client:
package com.anxpp.io.calculator.netty; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import java.util.Scanner; public class Client implements Runnable{ static ClientHandler client = new ClientHandler(); public static void main(String[] args) throws Exception { new Thread(new Client()).start(); @SuppressWarnings("resource") Scanner scanner = new Scanner(System.in); while(client.sendMsg(scanner.nextLine())); } @Override public void run() { String host = "127.0.0.1"; int port = 9090; EventLoopGroup workerGroup = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); b.group(workerGroup); b.channel(NioSocketChannel.class); b.option(ChannelOption.SO_KEEPALIVE, true); b.handler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(client); } }); ChannelFuture f = b.connect(host, port).sync(); f.channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); } finally { workerGroup.shutdownGracefully(); } } }
ClientHandler:
package com.anxpp.io.calculator.netty; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import java.io.UnsupportedEncodingException; public class ClientHandler extends ChannelInboundHandlerAdapter { ChannelHandlerContext ctx; /** * tcp链路简历成功后调用 */ @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { this.ctx = ctx; } public boolean sendMsg(String msg){ System.out.println("客户端发送消息:"+msg); byte[] req = msg.getBytes(); ByteBuf m = Unpooled.buffer(req.length); m.writeBytes(req); ctx.writeAndFlush(m); return msg.equals("q")?false:true; } /** * 收到服务器消息后调用 * @throws UnsupportedEncodingException */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws UnsupportedEncodingException { ByteBuf buf = (ByteBuf) msg; byte[] req = new byte[buf.readableBytes()]; buf.readBytes(req); String body = new String(req,"utf-8"); System.out.println("服务器消息:"+body); } /** * 发生异常时调用 */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } }
3、用于计算的工具类
package com.anxpp.io.utils; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; public enum Calculator { Instance; private final static ScriptEngine jse = new ScriptEngineManager().getEngineByName("JavaScript"); public Object cal(String expression) throws ScriptException{ return jse.eval(expression); } }
4、测试
分别启动服务端和客户端,然后再客户端控制台输入表达式:
1+5+5+5+5+5 客户端发送消息:1+5+5+5+5+5 服务器消息:26 156158*458918+125615 客户端发送消息:156158*458918+125615 服务器消息:7.1663842659E10 1895612+555+5+5+5+5+5+5+5-5*4/4 客户端发送消息:1895612+555+5+5+5+5+5+5+5-5*4/4 服务器消息:1896197
可以看到服务端返回的结果。
查看服务端控制台:
服务器开启:9090 收到客户端消息:1+5+5+5+5+5 收到客户端消息:156158*458918+125615 收到客户端消息:1895612+555+5+5+5+5+5+5+5-5*4/4
5、更多
相关文章:
Java 网络IO编程总结(BIO、NIO、AIO均含完整实例代码)
本文例子以及Java BIO NIO AIO例子的源码Git地址:https://github.com/anxpp/Java-IO.git
后续会继续更新Netty相关内容,直到一个简陋的通讯服务器完成。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持码农之家。
相关教程
-
Java抓包工具fiddler实现请求转发
Fiddler是一个http协议调试代理工具,本文主要介绍了Java抓包工具fiddler实现请求转发,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
发布时间:2019-07-23
-
零基础学Java编程需要具备哪些条件?
零基础学Java编程需要具备哪些条件?码农之家独创PDT教学方法,可以快速帮助学员掌握Java零基础知识
发布时间:2021-06-06
-
Java开发实例大全:基础卷
本书超级详尽的实例大全,源码分析的案头手册,提高效率的绝好帮手,45个方向,1201个实例案例,java编程类四库全书,分门别类常用编程实例,《java开发实战1200例》之全新升级
大小:176 MBJava实例电子书
-
Java学习指南
《Java学习指南(第4版)(上、下册)》 是畅销Java学习指南的最新版,详细介绍了Java 6和Java 7的语言特性和API。本书全面介绍了Java的基础知识,力图通过完备地介绍Java语言、其类库、编程技术以及
大小:179.5 MBJava电子书
-
Java程序设计基础
《Java程序设计基础》是一本关于java的电子书资源,涉及Java、程序设计等相关内容,本文提供大小为158MB的扫描第5PDF格式电子书下载,希望大家能够喜欢。
大小:158 MBjava电子书
-
阿里巴巴Java开发手册
这本书愿景是码出高效,码出质量,提炼阿里巴巴集团技术团队的集体编程经验和软件设计智慧,浓缩成为立体的编程规范和实践,适合计算机相关行业的管理者和研发人员、高等院校的计算机专业师生、求职者等阅读
大小:27.5 MBJava开发电子书
-
Java性能权威指南
本书对Java 7和Java 8中影响性能的因素展开了全面深入的介绍,讲解传统上影响应用性能的JVM特征,包括即时编译器、垃圾收集、语言特征等。内容包括:用G1垃圾收集器应用的吞吐量;使用Ja
大小:66.1 MBJava电子书
-
企业级Java EE架构设计精深实践
本书全面、深入介绍了企业级Java EE设计的相关内容,内容涵盖了Java EE架构设计的常见问题。语言简洁,思路清晰,示例丰富、完整,适合具有一定Java基础的读者阅读,尤其适合从事企业级Java EE软件架构和设计的人员阅读
大小:84.3 MBJava电子书
-
Effective Java
本书介绍了在Java编程中78条极具实用价值的经验规则,这些经验规则涵盖了大多数开发人员每天所面临的问题的解决方案。通过对Java平台设计专家所使用的技术的全面描述,揭示了应该做什么
大小:56 MBjava电子书