本文共 5190 字,大约阅读时间需要 17 分钟。
Netty 是一个高性能、异步事件驱动的 NIO 框架,基于 Java NIO 提供的 API 实现,封装了 NIO 中的一些难以使用和 bug。Netty 提供了简单易用的 API,能够快速开发可维护的高性能协议服务器和客户端,同时修复了 JDK NIO 中已知的 bug。
Netty 在 Linux 上的性能优于 AIO,因为 AIO 的底层实现仍依赖 EPOLL,缺乏优势。AIO 接收数据需要预先分配缓存,可能导致内存浪费。此外,AIO 处理回调结果速度较慢,难以满足高并发需求。Netty 作者原话:“Not faster than NIO (epoll) on unix systems (which is true) There is no daragram suppport Unnecessary threading model (too much abstraction without usage)”
Netty 采用事件驱动架构,核心组件包括:
public class MyServer { private int port; public MyServer(int port) { this.port = port; } public static void main(String[] args) throws InterruptedException { MyServer myServer = new MyServer(19091); System.out.println("服务器即将启动"); myServer.start(); System.out.println("服务器已关闭"); } private void start() throws InterruptedException { NioEventLoopGroup bossGroup = new NioEventLoopGroup(); try { ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(bossGroup) .channel(NioServerSocketChannel.class) .localAddress(new InetSocketAddress(port)) .childHandler(new ChannelInitializer<>() { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { socketChannel.pipeline().addLast(new MyServerHandler()); } }); System.out.println("MyServer 服务端已经准备就绯..."); ChannelFuture channelFuture = bootstrap.bind().sync(); System.out.println("服务器启动完成"); channelFuture.channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully().sync(); } }} public class MyServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("MyServerHandler 连接已建立..."); super.channelActive(ctx); } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf in = (ByteBuf) msg; System.out.println("Server Accept Client Context (" + ctx.channel().remoteAddress() + ")消息 - " + in.toString(CharsetUtil.UTF_8)); ctx.writeAndFlush(in); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { ByteBuf byteBuf = Unpooled.copiedBuffer("Server Receive Client msg", CharsetUtil.UTF_8); ctx.writeAndFlush(byteBuf); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { ctx.close(); }} public class MyClient { private String host; private int port; public MyClient(String host, int port) { this.host = host; this.port = port; } public static void main(String[] args) throws InterruptedException { MyClient myClient = new MyClient("127.0.0.1", 19091); System.out.println("客户端即将启动"); myClient.start(); System.out.println("客户端已关闭"); } private void start() throws InterruptedException { NioEventLoopGroup bossGroup = new NioEventLoopGroup(); try { Bootstrap bootstrap = new Bootstrap(); bootstrap.group(bossGroup) .channel(NioSocketChannel.class) .remoteAddress(new InetSocketAddress(host, port)) .handler(new ChannelInitializer<>() { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { socketChannel.pipeline().addLast(new MyClientHandler()); } }); System.out.println("客户端准备就绯,随时可以连接服务端"); ChannelFuture channelFuture = bootstrap.connect().sync(); System.out.println("客户端启动连接完成"); channelFuture.channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully().sync(); } }} public class MyClientHandler extends SimpleChannelInboundHandler { @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { ByteBuf byteBuf = Unpooled.copiedBuffer(" Hello, Netty", CharsetUtil.UTF_8); ctx.writeAndFlush(byteBuf); } @Override protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf in = (ByteBuf) msg; System.out.println("Client Accept Server (" + ctx.channel().remoteAddress() + ")消息 - " + in.toString(CharsetUtil.UTF_8)); }} 服务端启动时会输出:
MyServer 服务端已经准备就绯...服务器启动完成
客户端启动时会输出:
客户端准备就绯,随时可以连接服务端客户端启动连接完成
通过以上示例,可以看到 Netty 的使用流程,完成了一个简单的客户端与服务端通信。更多 Netty 功能可以参考官方文档深入学习。
转载地址:http://hccfk.baihongyu.com/