网易首页 > 网易号 > 正文 申请入驻

netty系列之:文本聊天室

0
分享至

简介

经过之前的系列文章,我们已经知道了netty的运行原理,还介绍了基本的netty服务搭建流程和消息处理器的写法。今天本文会给大家介绍一个更加复杂的例子,文本聊天室。

聊天室的工作流程

今天要介绍的是文本聊天室,对于文本聊天室来说,首先需要建立一个服务器,用于处理各个客户端的连接,对于客户端来说,需要建立和服务器的连接,然后向服务器输入聊天信息。服务器收到聊天信息之后,会对消息进行响应,并将消息返回至客户端,这样一个聊天室的流程就完成了。

文本处理器

之前的文章中,我们有提到过,netty的传输只支持ByteBuf类型,对于聊天室直接输入的字符串是不支持的,需要对字符串进行encode和decode转换。

之前我们介绍的encode和decode的类叫做ObjectDecoder和ObjectEncoder。今天我们再介绍两个专门处理字符串的StringDecoder和StringEncoder。

StringEncoder要比ObjectEncoder简单很多,因为对于对象来说,我们还需要在Byte数组的头部设置Byte数组的大小,从而保证对象所有数据读取正确。对于String来说,就比较简单了,只需要保证一次读入的数据都是字符串即可。

StringEncoder继承自MessageToMessageEncoder,其核心的encode代码如下:

protected void encode(ChannelHandlerContext ctx, CharSequence msg, List out) throws Exception {
if (msg.length() == 0) {
return;

out.add(ByteBufUtil.encodeString(ctx.alloc(), CharBuffer.wrap(msg), charset));
}

从上面的代码可以看出,核心实际上是调用了ByteBufUtil.encodeString方法,将String转换成了ByteBuf。

对于字符串编码来说,还需要界定一个编码的范围,比如我们需要知道需要一次编码多少字符串,一般来说我们通过回车符来界定一次字符串输入的结束。

netty也提供了这样的非常便利的类叫做DelimiterBasedFrameDecoder,通过传入不同的Delimiter,我们可以将输入拆分成不同的Frame,从而对一行字符串进行处理。

new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()))

我再看一下StringDecoder的核心代码,StringDecoder继承自MessageToMessageDecoder:

protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) throws Exception {
out.add(msg.toString(charset));

通过调用ByteBuf的toString方法,将BuyteBuf转换成为字符串,并且输出到channel中。

初始化ChannelHandler

在initChannel的时候,我们需要向ChannelPipeline中添加有效的Handler。对于本例来说,需要添加StringDecoder、StringEncoder、DelimiterBasedFrameDecoder和真正处理消息的自定义handler。

我们将初始化Pipeline的操作都放在一个新的ChatServerInitializer类中,这个类继承自ChannelInitializer,其核心的initChannel方法如下:

public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
// 添加行分割器
pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
// 添加String Decoder和String Encoder,用来进行字符串的转换
pipeline.addLast(DECODER);
pipeline.addLast(ENCODER);
// 最后添加真正的处理器
pipeline.addLast(SERVER_HANDLER);

ChatServerInitializer在Bootstrap中的childHandler中进行添加:

childHandler(new ChatServerInitializer())
真正的消息处理逻辑

有了上面的逻辑之后,我们最后只需要专注于真正的消息处理逻辑即可。

这里我们的逻辑是当客户端输入“再见”的时候,就关闭channel,否则就将消息回写给客户端。

其核心逻辑如下:

public void channelRead0(ChannelHandlerContext ctx, String request) throws Exception {
// 如果读取到"再见"就关闭channel
String response;
// 判断是否关闭
boolean close = false;
if (request.isEmpty()) {
response = "你说啥?\r\n";
} else if ("再见".equalsIgnoreCase(request)) {
response = "再见,我的朋友!\r\n";
close = true;
} else {
response = "你是不是说: '" + request + "'?\r\n";

// 写入消息
ChannelFuture future = ctx.write(response);
// 添加CLOSE listener,用来关闭channel
if (close) {
future.addListener(ChannelFutureListener.CLOSE);
}
}

通过判断客户端的出入,来设置是否关闭按钮,这里的关闭channel是通过向ChannelFuture中添加ChannelFutureListener.CLOSE来实现的。

ChannelFutureListener.CLOSE是一个ChannelFutureListener,它会在channel执行完毕之后关闭channel,事实上这是一个非常优雅的关闭方式。

ChannelFutureListener CLOSE = new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) {
future.channel().close();

对于客户端来说,其核心就是从命令行读取输入,这里使用InputStreamReader接收命令行输入,并使用BufferedReader对其缓存。

然后将命令行输入通过调用 ch.writeAndFlush写入到channel中,最后监听命令行输入,如果监听到“再见“,则等待server端关闭channel,其核心代码如下。

// 从命令行输入
ChannelFuture lastWriteFuture = null;
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
for (;;) {
String line = in.readLine();
if (line == null) {
break;
// 将从命令行输入的一行字符写到channel中
lastWriteFuture = ch.writeAndFlush(line + "\r\n");
// 如果输入'再见',则等待server端关闭channel
if ("再见".equalsIgnoreCase(line)) {
ch.closeFuture().sync();
break;

// 等待所有的消息都写入channel中
if (lastWriteFuture != null) {
lastWriteFuture.sync();
}

总结

经过上面的介绍,一个简单的聊天室就建成了。后续我们会继续探索更加复杂的应用,希望大家能够喜欢。

本文已收录于 http://www.flydean.com/10-netty-chat/

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
我今年55了,想用血泪教训告诉你:不要跟任何人,包括你的父母、子女、枕边人,分享这4件事

我今年55了,想用血泪教训告诉你:不要跟任何人,包括你的父母、子女、枕边人,分享这4件事

东林夕亭
2026-03-27 09:07:57
英超大地震!曼城恐扣 60 分直接降级,王朝一夜崩塌

英超大地震!曼城恐扣 60 分直接降级,王朝一夜崩塌

奶盖熊本熊
2026-03-29 04:47:36
中文互联网上,伊军已经把美国以色列干趴下了

中文互联网上,伊军已经把美国以色列干趴下了

钱唐胡公子
2026-03-28 08:00:09
以色列最担心的事发生:伊朗送出“大礼”,特朗普的反应出人意料

以色列最担心的事发生:伊朗送出“大礼”,特朗普的反应出人意料

空天力量
2026-03-28 17:14:31
不堪入目,工作群上演“活春宫”,网友说:这锅AI不背!

不堪入目,工作群上演“活春宫”,网友说:这锅AI不背!

黯泉
2026-03-29 14:47:55
内存条崩了,囤货大户疯狂抛售,把内存条当理财的人,全砸手里了

内存条崩了,囤货大户疯狂抛售,把内存条当理财的人,全砸手里了

离离言几许
2026-03-29 18:46:33
为什么要加入CPTPP?啃不下这6块硬骨头,未来中国可能会很难!

为什么要加入CPTPP?啃不下这6块硬骨头,未来中国可能会很难!

世界圈
2026-03-28 12:25:46
广东省将会出现下一个 “深圳”,并不是广州,而是这个城市

广东省将会出现下一个 “深圳”,并不是广州,而是这个城市

娱乐的硬糖吖
2026-03-28 05:37:04
美媒:美国全国范围爆发反对特朗普政府集会,预计超900万人参与,或为“美国历史上规模最大”抗议活动

美媒:美国全国范围爆发反对特朗普政府集会,预计超900万人参与,或为“美国历史上规模最大”抗议活动

环球网资讯
2026-03-29 09:27:36
“直接崩了,一天掉了一百多元!”有人疯狂抛售,国际巨头接连发布新技术……格局将被改变?

“直接崩了,一天掉了一百多元!”有人疯狂抛售,国际巨头接连发布新技术……格局将被改变?

都市快报橙柿互动
2026-03-29 12:26:05
一分钱不要,也得让你长记性!业主车位被霸占10天,奥迪车大变脸

一分钱不要,也得让你长记性!业主车位被霸占10天,奥迪车大变脸

火山詩话
2026-03-29 17:05:43
全国猪价跌破5元 创历史新低

全国猪价跌破5元 创历史新低

财联社
2026-03-29 18:02:12
比赖清德更狂的人出现了,只要她当上台湾领导人,解放军必定收台

比赖清德更狂的人出现了,只要她当上台湾领导人,解放军必定收台

共工之锚
2026-03-29 18:26:19
东风导弹泄密案!间谍郭万钧一家三口,全部被处以死刑

东风导弹泄密案!间谍郭万钧一家三口,全部被处以死刑

谈史论天地
2026-03-29 16:10:03
河南一法官被通报索贿涉44条人命遭捕,竟毫发无损稳坐审判席审案

河南一法官被通报索贿涉44条人命遭捕,竟毫发无损稳坐审判席审案

追月数星
2026-03-29 16:49:01
刚刚,薛之谦在广州演唱会现场宣布退票!“一整个水灾现场”“荧光棒都不亮了”

刚刚,薛之谦在广州演唱会现场宣布退票!“一整个水灾现场”“荧光棒都不亮了”

都市快报橙柿互动
2026-03-29 22:15:25
2年和领导开房410次!从临时工“睡”成处长,南航女经理升迁之路

2年和领导开房410次!从临时工“睡”成处长,南航女经理升迁之路

就一点
2026-03-28 17:42:50
广铁致歉受强降雨龙卷风影响部分列车晚点,乘客讲述隧道内停车断电4小时经历

广铁致歉受强降雨龙卷风影响部分列车晚点,乘客讲述隧道内停车断电4小时经历

澎湃新闻
2026-03-29 21:18:27
特朗普透露卸任后去向,想当几个国的领导人?霍尔木兹海峡变“特朗普海峡”?

特朗普透露卸任后去向,想当几个国的领导人?霍尔木兹海峡变“特朗普海峡”?

新民周刊
2026-03-29 08:55:09
张雪峰的灵车细节让人泪奔,车尾挂着一棵竹子,上面系着他的衣服

张雪峰的灵车细节让人泪奔,车尾挂着一棵竹子,上面系着他的衣服

魔都姐姐杂谈
2026-03-28 18:18:48
2026-03-30 04:07:00
flydean程序那些事
flydean程序那些事
最通俗的解读,最深刻的干货!
356文章数 438关注度
往期回顾 全部

科技要闻

马斯克承认xAI"建错了",11位创始人均离职

头条要闻

伊朗议长:美航母遭受巨大损失 我们绝不接受屈辱

头条要闻

伊朗议长:美航母遭受巨大损失 我们绝不接受屈辱

体育要闻

绝杀卫冕冠军后,他单手指天把胜利献给父亲

娱乐要闻

汪峰定律再现!李荣浩喊话单依纯侵权

财经要闻

Kimi、Minimax 们的算力荒

汽车要闻

岚图泰山X8配置曝光 四激光雷达/华为新一代座舱

态度原创

手机
艺术
本地
教育
房产

手机要闻

骁龙8 Elite Gen6系列规格大揭秘:LPDDR6、Adreno 850,都来了!

艺术要闻

不守墨矩的扬州八怪

本地新闻

在潍坊待了三天,没遇到一个“潍坊人”

教育要闻

建议给家长放春秋假,否则的话,学生放春秋假就失去意义

房产要闻

首日430组来访,单日120组认筹!海口首个真四代,彻底爆了!

无障碍浏览 进入关怀版