当前位置: 首页 > news >正文

Netty网络聊天室及扩展序列化算法

一、前言

Netty是一个基于Java的高性能、事件驱动的网络应用框架,广泛应用于各种网络通信场景。本文将介绍如何使用Netty构建一个简单的网络聊天室,并扩展序列化算法来提高数据传输效率和灵活性。

二、Netty网络聊天室的实现

1. 项目结构

我们将使用Maven构建项目,项目结构如下:

netty-chatroom/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   ├── server/
│   │   │   │   ├── ChatServer.java
│   │   │   │   ├── ChatServerInitializer.java
│   │   │   │   ├── ChatServerHandler.java
│   │   │   ├── client/
│   │   │   │   ├── ChatClient.java
│   │   │   │   ├── ChatClientInitializer.java
│   │   │   │   ├── ChatClientHandler.java
│   │   ├── resources/
│   │       ├── log4j.properties
├── pom.xml
​

2. 服务器端实现

ChatServer.java
package server;import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;public class ChatServer {private final int port;public ChatServer(int port) {this.port = port;}public void start() throws Exception {NioEventLoopGroup bossGroup = new NioEventLoopGroup();NioEventLoopGroup workerGroup = new NioEventLoopGroup();try {ServerBootstrap b = new ServerBootstrap();b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new ChatServerInitializer()).option(ChannelOption.SO_BACKLOG, 128).childOption(ChannelOption.SO_KEEPALIVE, true);ChannelFuture f = b.bind(port).sync();f.channel().closeFuture().sync();} finally {workerGroup.shutdownGracefully();bossGroup.shutdownGracefully();}}public static void main(String[] args) throws Exception {new ChatServer(8080).start();}
}
​
ChatServerInitializer.java
package server;import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;public class ChatServerInitializer extends ChannelInitializer<SocketChannel> {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast(new LoggingHandler(LogLevel.INFO));ch.pipeline().addLast(new StringDecoder());ch.pipeline().addLast(new StringEncoder());ch.pipeline().addLast(new ChatServerHandler());}
}
​
ChatServerHandler.java
package server;import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;public class ChatServerHandler extends SimpleChannelInboundHandler<String> {private static final ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);@Overridepublic void handlerAdded(ChannelHandlerContext ctx) throws Exception {channels.add(ctx.channel());}@Overridepublic void handlerRemoved(ChannelHandlerContext ctx) throws Exception {channels.remove(ctx.channel());}@Overrideprotected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {for (var channel : channels) {if (channel != ctx.channel()) {channel.writeAndFlush("[Client] " + ctx.channel().remoteAddress() + " says: " + msg + "\n");} else {channel.writeAndFlush("[You] " + msg + "\n");}}}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {cause.printStackTrace();ctx.close();}
}
​

3. 客户端实现

ChatClient.java
package client;import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;public class ChatClient {private final String host;private final int port;public ChatClient(String host, int port) {this.host = host;this.port = port;}public void start() throws Exception {NioEventLoopGroup group = new NioEventLoopGroup();try {Bootstrap b = new Bootstrap();b.group(group).channel(NioSocketChannel.class).handler(new ChatClientInitializer());ChannelFuture f = b.connect(host, port).sync();f.channel().closeFuture().sync();} finally {group.shutdownGracefully();}}public static void main(String[] args) throws Exception {new ChatClient("localhost", 8080).start();}
}
​
ChatClientInitializer.java
package client;import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;public class ChatClientInitializer extends ChannelInitializer<SocketChannel> {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast(new LoggingHandler(LogLevel.INFO));ch.pipeline().addLast(new StringDecoder());ch.pipeline().addLast(new StringEncoder());ch.pipeline().addLast(new ChatClientHandler());}
}
​
ChatClientHandler.java
package client;import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;public class ChatClientHandler extends SimpleChannelInboundHandler<String> {@Overrideprotected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {System.out.println(msg);}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {cause.printStackTrace();ctx.close();}
}
​

三、扩展序列化算法

为了提高数据传输效率,我们可以扩展Netty的序列化算法。Netty默认提供的序列化算法包括Java序列化、JSON、Protobuf等。下面介绍如何使用Protobuf进行序列化。

1. 配置Protobuf

首先,在 pom.xml中添加Protobuf依赖:

<dependency><groupId>com.google.protobuf</groupId><artifactId>protobuf-java</artifactId><version>3.19.1</version>
</dependency>
​

2. 定义Protobuf消息

创建一个 chat.proto文件:

syntax = "proto3";package chat;message ChatMessage {string from = 1;string to = 2;string content = 3;
}
​

编译Protobuf文件生成Java类:

protoc --java_out=src/main/java src/main/proto/chat.proto
​

3. 修改服务器端处理器

在服务器端,使用Protobuf进行消息的序列化和反序列化:

package server;import chat.ChatMessage;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;public class ChatServerHandler extends SimpleChannelInboundHandler<ChatMessage> {private static final ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);@Overridepublic void handlerAdded(ChannelHandlerContext ctx) throws Exception {channels.add(ctx.channel());}@Overridepublic void handlerRemoved(ChannelHandlerContext ctx) throws Exception {channels.remove(ctx.channel());}@Overrideprotected void channelRead0(ChannelHandlerContext ctx, ChatMessage msg) throws Exception {for (var channel : channels) {if (channel != ctx.channel()) {channel.writeAndFlush(msg.toBuilder().setContent("[Client] " + ctx.channel().remoteAddress() + " says: " + msg.getContent()).build());} else {channel.writeAndFlush(msg.toBuilder().setContent("[You] " + msg.getContent()).build());}}}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {cause.printStackTrace();ctx.close();}
}
​

4. 修改客户端处理器

在客户端,同样使用Protobuf进行消息的序列化和反序列化:

package client;import chat.ChatMessage;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;public class ChatClientHandler extends SimpleChannelInboundHandler<ChatMessage> {@Overrideprotected void channelRead0(ChannelHandlerContext ctx, ChatMessage msg) throws Exception {System.out.println(msg.getContent());}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {cause.printStackTrace();ctx.close();}
}
http://www.dtcms.com/a/287209.html

相关文章:

  • 2025年睿抗机器人开发者大赛CAIP-编程技能赛(省赛)-RoboCom 世界机器人开发者大赛-本科组
  • 微软原版系统下载的几个好用网站
  • LVS——nat模式
  • 【ArcGIS技巧】最近分享的GIS插件总结与优化
  • 实战分享:Web3 前端开发Defi项目
  • 【设计模式C#】外观模式(用于解决客户端对系统的许多类进行频繁沟通)
  • 【Unity编辑器开发GUI.Window】
  • 企业运维实战:Jenkins 依赖 JDK21 与应用需 JDK1.8 共存方案(含流水线配置)
  • 软件工程:可行性分析的任务及报告
  • 【NLP舆情分析】基于python微博舆情分析可视化系统(flask+pandas+echarts) 视频教程 - 基于wordcloud库实现词云图
  • 使用nvm安装node、npm、pnpm以及编译项目教程
  • 告别项目混乱:基于 pnpm + Turborepo 的现代化 Monorepo 工程化最佳实践
  • 【音视频协议篇】RTSP系列
  • gitlab+jenkins
  • 综合实验--eNSP实验
  • k8s 基本架构
  • Flowable31动态表单-----------------------终章
  • AI编程工具对比:Cursor、GitHub Copilot与Claude Code
  • bws-rs:Rust 编写的 S3 协议网关框架,支持灵活后端接入
  • 【Linux】AKHQ实现kafka可视化
  • 电力载波通信技术全景解析:从历史演进到智能电网创新应用
  • 【Linux服务器】-MySQL数据库参数调优
  • 打造高效订单处理!ZKmall开源商城的统一履约中心架构解析
  • 本地部署开源的 AI 驱动的搜索引擎 Perplexica 并实现外部访问
  • 【黑马SpringCloud微服务开发与实战】(三)微服务01
  • 快速上手AI整合包!GPT-SoVITS-v2打包教程,解锁AIStarter应用市场潜力
  • freertos任务调度关键函数理解
  • 笔试强训——第一周
  • 标准文件和系统文件I/O
  • 鸿蒙与web混合开发双向通信