在前两篇文章中,我们深入探讨了 Netty 的 IO 模型以及其核心组件的工作原理。本篇文章将通过一个实际的聊天服务器示例,展示如何使用 Netty 构建高性能的网络应用。
一、项目结构
项目主要包含以下几个部分:
-
ChatServer:服务器启动类
-
ChatServerInitializer:初始化通道的处理器
-
ChatServerHandler:处理业务逻辑
二、服务器启动类
public class ChatServer {
public static void main(String[] args) throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChatServerInitializer());
ChannelFuture f = b.bind(8000).sync();
f.channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
上述代码中,我们创建了两个事件循环组:bossGroup用于接受客户端连接,workerGroup 用于处理已连接的客户端的网络读写。通过 ServerBootstrap 配置服务器,并绑定端口 8000。
三、通道初始化器
public class ChatServerInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new StringDecoder());
pipeline.addLast(new StringEncoder());
pipeline.addLast(new ChatServerHandler());
}
}
在通道初始化器中,我们添加了三个处理器:StringDecoder 用于将字节解码为字符串,StringEncoder 用于将字符串编码为字节,ChatServerHandler 用于处理业务逻辑。
四、业务逻辑处理器
public class ChatServerHandler extends SimpleChannelInboundHandler<String> {
private static ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
@Override
public void handlerAdded(ChannelHandlerContext ctx) {
Channel incoming = ctx.channel();
channels.writeAndFlush("[SERVER] - " + incoming.remoteAddress() + " 加入\n");
channels.add(incoming);
}
@Override
public void handlerRemoved(ChannelHandlerContext ctx) {
Channel incoming = ctx.channel();
channels.writeAndFlush("[SERVER] - " + incoming.remoteAddress() + " 离开\n");
channels.remove(incoming);
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) {
Channel incoming = ctx.channel();
for (Channel channel : channels) {
if (channel != incoming) {
channel.writeAndFlush("[" + incoming.remoteAddress() + "] " + msg + "\n");
} else {
channel.writeAndFlush("[你] " + msg + "\n");
}
}
}
}
在 ChatServerHandler 中,我们使用 ChannelGroup 来管理所有连接的客户端。当有新的客户端连接或断开时,服务器会广播相应的消息。当服务器接收到某个客户端发送的消息时,会将该消息广播给所有其他客户端。
五、测试聊天服务器
启动服务器后,可以使用多个客户端(如 Telnet)连接到服务器:
telnet localhost 8000
连接成功后,输入的消息将被广播给所有其他已连接的客户端。
六、总结
通过本篇文章,我们实现了一个基于 Netty 的简易聊天服务器,展示了 Netty 在处理多客户端通信方面的强大能力。在实际应用中,可以在此基础上扩展更多功能,如用户认证、私聊、群聊等。