Netty学习
是什么
想象一下你要在两个城市之间建立一条高效的物流系统:
- 传统方式(BIO):每来一件货物(一个请求),我就派一辆卡车和一个司机专门负责这趟运输。司机要一直等到货物装完、运输、卸完才能回来接下一单。如果货物没到,司机就得空等,非常浪费资源。
- Netty 方式(NIO):我建立一个智能物流中心(Netty)。这个中心有一个总调度员(
Reactor
线程),他负责盯着所有货车的状态(连接通道是否就绪)。一旦某辆货车的货物准备好了(数据就绪),调度员就通知一个空闲的装卸工(Worker
线程)去处理这辆车的装卸。这样,少量的司机和装卸工就能处理海量的货物。
结论:Netty 是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能服务器和客户端。它极大地简化了网络编程,让你不用从底层 Socket 开始苦苦折腾。
入门
基于 Netty 框架的简单客户端 - 服务器通信功能
基本目录:
其中:
java/
└── com/└── netty/├── NettyClient.java // 客户端启动类├── NettyServer.java // 服务端启动类├── client/ // 客户端相关组件│ ├── ClientInitializer.java // 客户端 Channel 初始化器│ └── ClientHandler.java // 客户端业务处理器└── server/ // 服务端相关组件├── ServerInitializer.java // 服务端 Channel 初始化器└── ServerHandler.java // 服务端业务处理器
服务器功能:
public class ServerHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {// 此时msg已经被解码器转为String,无需手动释放String in = (String) msg;System.out.println("Server 接收: " + in);// 直接发送字符串,编码器会自动转为ByteBufString response = "Hello from server!";ctx.writeAndFlush(response);}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {cause.printStackTrace();ctx.close();}
}
public class ServerInitializer extends ChannelInitializer<SocketChannel> {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();// 添加字符串解码器pipeline.addLast(new StringDecoder());// 添加字符串编码器pipeline.addLast(new StringEncoder());// 添加自定义的处理器pipeline.addLast(new ServerHandler());}}
public class NettyServer {public static void main(String[] args) throws InterruptedException {EventLoopGroup bossGroup = new NioEventLoopGroup();//处理连接请求EventLoopGroup workerGroup = new NioEventLoopGroup();//处理读写事件try {// 创建服务器启动引导类ServerBootstrap b = new ServerBootstrap();// 配置服务器参数b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) // 使用NIO传输通道.childHandler(new ServerInitializer()); // 设置业务处理器// 绑定端口并启动服务器ChannelFuture f = b.bind(8080).sync();System.out.println("Server started on port 8080");// 等待服务器通道关闭f.channel().closeFuture().sync();} finally {// 关闭EventLoopGroupworkerGroup.shutdownGracefully();bossGroup.shutdownGracefully();}}
}
- 监听本地 8080 端口
- 接收客户端发送的字符串消息并打印
- 收到消息后,向客户端返回 “Hello from server!” 响应
客户端功能:
public class ClientHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {// 直接发送字符串,编码器会自动转为ByteBufString msg = "Hello from client!";ctx.writeAndFlush(msg);}@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {// 此时msg已经被解码器转为StringString in = (String) msg;System.out.println("Client 接收: " + in);ctx.close();}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {cause.printStackTrace();ctx.close();}
}
public class ClientInitializer extends ChannelInitializer<SocketChannel> {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();pipeline.addLast(new StringDecoder());pipeline.addLast(new StringEncoder());pipeline.addLast(new ClientHandler());}
}
public class NettyClient {public static void main(String[] args) throws InterruptedException {// 创建EventLoopGroup实例EventLoopGroup group = new NioEventLoopGroup(); // 处理I/O操作和业务逻辑try {// 创建客户端启动引导类Bootstrap b = new Bootstrap();// 配置客户端参数b.group(group).channel(NioSocketChannel.class) // 使用NIO套接字通道.handler(new ClientInitializer()); // 设置业务处理器// 连接服务器ChannelFuture f = b.connect("localhost", 8080).sync();// 等待连接关闭f.channel().closeFuture().sync();} finally {// 优雅关闭EventLoopGroupgroup.shutdownGracefully();}}
}
- 连接本地 8080 端口的服务器
- 连接成功后向服务器发送 “Hello from client!” 消息
- 接收服务器返回的响应消息并打印
- 完成通信后关闭连接
时间线:
- 客户端连接服务器 (TCP握手完成)
- 客户端 channelActive() 触发 → 发送 “Hello from client!”
- 服务器收到数据 → channelRead() 触发 → 发送 “Hello from server!”
- 客户端收到响应 → channelRead() 触发 → 关闭连接
在这其中,Netty起作用如下:
代替原生 Java NIO:
// Netty 封装了复杂的 NIO 操作
EventLoopGroup group = new NioEventLoopGroup();
Bootstrap b = new Bootstrap();
b.group(group).channel(NioSocketChannel.class) // Netty 提供的 NIO 通道实现.handler(new ClientInitializer());
提供现成的编解码器:
pipeline.addLast(new StringDecoder()); // 字节 → 字符串
pipeline.addLast(new StringEncoder()); // 字符串 → 字节
事件模型:
public class ClientHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelActive(ChannelHandlerContext ctx) {// 连接建立时自动回调}@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) {// 收到数据时自动回调}
}
管道机制:
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new StringDecoder()); // 处理器1:解码
pipeline.addLast(new StringEncoder()); // 处理器2:编码
pipeline.addLast(new ServerHandler()); // 处理器3:业务逻辑
ByteBuf:
// 底层使用 Netty 的高效缓冲区
// StringEncoder 自动将 String 转换为优化的 ByteBuf
ctx.writeAndFlush(response);
自动处理:
- TCP 连接的建立和维护
- 连接的超时和重连
- 优雅的关闭和资源释放
// Netty 自动管理连接生命周期
ChannelFuture f = b.bind("localhost", 8080).sync();
f.channel().closeFuture().sync();
感谢阅读>W<