本节 通过一个简单的例子,说明一下netty的使用:
该示例创建了一个Echo服务器,它接收客户端发送的消息并原样回传:
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
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 EchoServer {
public static void main(String[] args) throws Exception {
// 配置主从线程组(EventLoopGroup)
EventLoopGroup bossGroup = new NioEventLoopGroup(1); // 主线程组,用于接受新连接
EventLoopGroup workerGroup = new NioEventLoopGroup(); // 工作线程组,用于处理已接受的连接
try {
// 创建引导类,并配置服务器参数
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class) // 使用NIO传输模式
.childHandler(new ChannelInitializer<SocketChannel>() { // 每个新连接建立时都会调用此方法初始化ChannelPipeline
@Override
protected void initChannel(SocketChannel ch) throws Exception {
// 添加处理器到通道的pipeline中
ch.pipeline().addLast(new EchoServerHandler()); // 自定义的业务处理器
}
});
// 绑定服务器监听端口
ChannelFuture f = b.bind(8080).sync();
// 等待服务器关闭
f.channel().closeFuture().sync();
} finally {
// 关闭所有线程组
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
// 自定义的Echo服务器处理器
public class EchoServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
ByteBuf in = (ByteBuf) msg; // 获取接收到的数据
System.out.println("Server received: " + in.toString(CharsetUtil.UTF_8));
// 将接收到的数据原样写回客户端
ctx.write(in);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) {
// 发送完数据后刷新缓冲区,触发实际的网络写操作
ctx.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
// 当异常发生时关闭连接
cause.printStackTrace();
ctx.close();
}
}
在这个例子中:
- EchoServer 类是Netty服务器的入口点,它启动了服务器并通过 ServerBootstrap 进行配置。
- EchoServerHandler 类实现了 ChannelInboundHandlerAdapter
接口,负责处理来自客户端的消息。在这里,它只是简单地将接收到的消息原样返回给客户端。