使用Netty实现一个简单的聊天服务器

✅作者简介:热爱Java后端开发的一名学习者,大家可以跟我一起讨论各种问题喔。
🍎个人主页:Hhzzy99
🍊个人信条:坚持就是胜利!
💞当前专栏:Netty
🥭本文内容:Netty实现一个简单的聊天服务器。

文章目录

  • 使用Netty实现一个简单的聊天服务器
    • 一、项目初始化与依赖配置
      • 1.1 创建Maven项目并添加依赖
    • 二、服务器端代码实现
      • 2.1 `ChatServer` - 服务端启动类
      • 2.2 `ChatServerHandler` - 消息处理器
    • 三、控制台客户端实现
      • 3.1 `ChatClient` - 客户端启动类
      • 3.2 `ChatClientHandler` - 客户端消息处理器
    • 四、启动与测试
      • 5.1 启动服务器和控制台客户端
  • 结语


使用Netty实现一个简单的聊天服务器

在本篇教程中,我们将通过Java的Netty框架实现一个简单的聊天服务器。

Netty是一款基于NIO(非阻塞IO)开发的网络框架,适用于高性能、高并发的应用场景。本文会详细展示如何通过Netty实现聊天服务器,实现控制台版客户端。

一、项目初始化与依赖配置

1.1 创建Maven项目并添加依赖

我们使用Maven管理依赖,首先在pom.xml文件中添加Netty依赖:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.example</groupId><artifactId>netty-chat</artifactId><version>1.0-SNAPSHOT</version><dependencies><!-- Netty 依赖 --><dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.68.Final</version></dependency></dependencies>
</project>

这样配置完成后,Maven会自动下载Netty的相关包。

二、服务器端代码实现

服务器端负责接受客户端连接、广播消息,并在客户端断开时进行处理。接下来我们编写服务器端启动类和处理器。

2.1 ChatServer - 服务端启动类

ChatServer类用于配置Netty服务器的基础设置,包括监听的端口、通道类型(NIO模式)和处理器链。服务器会监听指定端口,并通过处理器将消息分发给各客户端。

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;public class ChatServer {private final int port;public ChatServer(int port) {this.port = port;  // 设置服务器监听的端口}public void start() throws InterruptedException {// bossGroup:接受客户端连接的线程组EventLoopGroup bossGroup = new NioEventLoopGroup(1);// workerGroup:处理客户端连接的数据传输EventLoopGroup workerGroup = new NioEventLoopGroup();try {// ServerBootstrap用于启动和配置Netty服务器ServerBootstrap b = new ServerBootstrap();b.group(bossGroup, workerGroup)  // 设置boss和worker线程组.channel(NioServerSocketChannel.class)  // 指定NIO传输的通道类型.option(ChannelOption.SO_BACKLOG, 1024)  // 设置队列容量.childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) {ch.pipeline().addLast(new StringDecoder());ch.pipeline().addLast(new StringEncoder());// 为每个客户端连接配置消息处理器ch.pipeline().addLast(new ChatServerHandler());}});// 绑定端口并启动服务器ChannelFuture f = b.bind(port).sync();System.out.println("Chat server started on port " + port);// 等待服务器关闭f.channel().closeFuture().sync();} finally {// 关闭资源bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}public static void main(String[] args) throws InterruptedException {int port = 8080;  // 定义服务器监听的端口号new ChatServer(port).start();  // 启动服务器}
}

2.2 ChatServerHandler - 消息处理器

ChatServerHandler类负责管理客户端连接和消息的广播。我们会在客户端加入时广播“用户加入”消息,并在消息接收时进行广播。

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
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 ChannelInboundHandlerAdapter  {// 使用ChannelGroup来保存所有的连接,便于消息广播private static final ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);// 当新的客户端连接加入时调用@Overridepublic void handlerAdded(ChannelHandlerContext ctx) throws Exception {Channel incoming = ctx.channel();// 广播消息给所有已连接的客户端,通知新的连接加入for (Channel channel : channels) {channel.writeAndFlush("[SERVER] - " + incoming.remoteAddress() + " joined\n");}channels.add(incoming);  // 将新连接加入ChannelGroup}// 当客户端断开连接时调用@Overridepublic void handlerRemoved(ChannelHandlerContext ctx) throws Exception {Channel outgoing = ctx.channel();// 广播消息给所有已连接的客户端,通知连接已断开for (Channel channel : channels) {channel.writeAndFlush("[SERVER] - " + outgoing.remoteAddress() + " left\n");}channels.remove(outgoing);  // 从ChannelGroup中移除断开的连接}// 当服务器接收到客户端发来的消息时调用@Overridepublic void channelRead(ChannelHandlerContext ctx, Object message) throws Exception {Channel incoming = ctx.channel();// 使用StringDecoder与StringEncoder编码解码消息,所以直接字符串String msg = (String) message;System.out.println("[client] : " + msg);// 向其他客户端广播消息,当前发送者不接收自己的消息for (Channel channel : channels) {if (channel != incoming) {channel.writeAndFlush("[" + incoming.remoteAddress() + "] " + msg + "\n");} else {channel.writeAndFlush("[you] " + msg + "\n");}}}// 当出现异常时调用@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {cause.printStackTrace();ctx.close();  // 关闭连接}
}

三、控制台客户端实现

在实现浏览器客户端之前,我们先用Java创建一个简单的控制台客户端,以便在控制台中测试服务器的基本功能。通过这种方式,我们可以在不使用HTML页面的情况下,验证服务器的消息广播和客户端连接是否正常工作。

3.1 ChatClient - 客户端启动类

ChatClient类用于建立与服务器的连接,并在连接成功后允许用户发送消息。

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
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.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;import java.util.Scanner;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 InterruptedException {EventLoopGroup group = new NioEventLoopGroup();try {Bootstrap b = new Bootstrap();b.group(group).channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) {ch.pipeline().addLast(new StringDecoder());ch.pipeline().addLast(new StringEncoder());ch.pipeline().addLast(new ChatClientHandler());}});Channel channel = b.connect(host, port).sync().channel();Scanner scanner = new Scanner(System.in);System.out.println("Enter your messages (type 'exit' to quit):");while (true) {String message = scanner.nextLine();if ("exit".equalsIgnoreCase(message)) {break;}channel.writeAndFlush(message + "\n");}} finally {group.shutdownGracefully();}}public static void main(String[] args) throws InterruptedException {new ChatClient("localhost", 8080).start();}
}

3.2 ChatClientHandler - 客户端消息处理器

ChatClientHandler类用于接收服务器的消息并在控制台显示。

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;public class ChatClientHandler extends SimpleChannelInboundHandler<String> {@Overrideprotected void channelRead0(ChannelHandlerContext ctx, String msg) {System.out.println(msg);  // 输出从服务器收到的消息}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {cause.printStackTrace();ctx.close();}
}

四、启动与测试

5.1 启动服务器和控制台客户端

  1. 启动ChatServer
  2. 启动ChatClient,进行消息测试。

我们启动服务端ChatServer
chatServer

接着再启动客户端ChatClient
chatClient

客户端ChatClient发送消息,并且服务端转发回来( [YOU] 那一行就是服务端转发回来的):
在这里插入图片描述
服务端接收到消息:
在这里插入图片描述


结语

本文通过实现简单的控制台客户端和HTML客户端,让大家更好地理解Netty服务器的工作原理。希望对大家有所帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/467160.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【HarmonyOS】鸿蒙应用低功耗蓝牙BLE的使用心得 (二)

【HarmonyOS】鸿蒙应用低功耗蓝牙BLE的使用心得 &#xff08;二&#xff09; 一、前言 目前鸿蒙应用的实现逻辑&#xff0c;基本都是参考和移植Android端来实现。针对BLE低功耗蓝牙来说&#xff0c;在鸿蒙化的实现过程中。我们发现了&#xff0c;鸿蒙独有的优秀点&#xff0c…

第六十三周周报 GCN-CNNGA

文章目录 week 63 GCN-CNNGA摘要Abstract1. 题目2. Abstract3. 文献解读3.1 Introduction3.2 创新点 4. 网络结构4.1 数据分析4.2 混合深度学习框架的发展4.3 Mul4.4 CNN block4.5 GCN block4.6 GRU block4.7 注意力机制4.8 模型评估标准 5. 实验结果5.1 不同邻接矩阵的性能评价…

geoserver+postgis 最短路径规划常见问题记录

一、说明 具体实现步骤可参考其他博文&#xff0c;下面的这个博主写的很详细&#xff0c;步骤很清晰&#xff0c;注释也很全。geoserverpostgis 最短路径规划_geoserver 最短路径 存储过程-CSDN博客 本次文章&#xff0c;仅记录过程中需要注意的方面。 二、数据预处理 目标&a…

石油安全理论知识题库 考试宝在线刷题

一、单选题&#xff08;每题有4个选项&#xff0c;其中只有1个是正确的&#xff0c;将正确的选项号填入括号内&#xff09; 1.新修订的《中华人民共和国安全生产法》于&#xff08; &#xff09;正式实施。 A、2014年1月1日 B、2014年12月1日 C、2015年1月1日 D、2015年…

航空标志灯技术革新:提升夜间飞行安全

航空标志灯 随着低空飞行活动的增多和新型飞行器&#xff08;如无人机、热气球和直升机&#xff09;的普及&#xff0c;地面重要设施的安全面临前所未有的挑战。因此&#xff0c;航空标志灯的安装变得尤为重要。它们通过提升城市天际线、广袤乡村、跨河桥梁及电力网络等复杂地…

前后端交互接口(三)

前后端交互接口&#xff08;三&#xff09; 前言 前两集我们先做了前后端交互接口的约定以及浅浅的阅读了一些proto代码。那么这一集我们就来看看一些重要的proto代码&#xff0c;之后把protobuffer给引入我们的项目当中&#xff01; gateway.proto 我们来看一眼我们的网关…

机器学习—sigmoid的替代品

Z状结肠激活函数&#xff0c;在隐藏层中&#xff0c;在输出层&#xff0c;因为用逻辑回归建立神经网络&#xff0c;创造了大量的逻辑回归单元&#xff0c;但是如果你使用其他激活函数&#xff0c;神经网络可以变得更加强大。 以需求预测为例&#xff0c;给定价格&#xff0c;航…

数据分析-44-时间序列预测之深度学习方法TCN

文章目录 1 TCN简介1.1 网络示意图1.2 TCN优点2 模拟应用2.1 模拟数据2.2 预处理创建滞后特征2.3 划分训练集和测试集2.4 创建TCN模型2.5 模型训练2.6 模型预测3 自定义my_TCN模型3.1 my_TCN()函数3.2 训练模型3.3 模型预测3.4 改进4 参考附录1 TCN简介 时间卷积网络(TCN)是…

2024最新AI绘画系统软件(Midjourney)+GPT4文档分析总结,多模态识图理解,AI文生图/图生图/混图生图(图像混合)

一、前言 人工智能的快速发展已成为全球关注的焦点&#xff0c;其应用领域广泛&#xff0c;涵盖绘图、语言处理、视频编辑等。前沿技术不仅推动科技创新&#xff0c;还在艺术创作、内容生产和商业实践等方面展示出巨大潜力。例如&#xff0c;AI语言模型显著提升了内容自动生成、…

input file检验成功之后才可以点击

input file检验成功之后才可以点击 需求 在上传发票前需要先填写发票号&#xff0c;然后点击选择文件直接完成上传功能 实现思路 在没有输入发票号之前&#xff0c;file按钮不可用不能点击&#xff0c;输入之后&#xff0c;按钮可用&#xff0c;点击之后选择文件&#xff…

每日OJ题_牛客_AB31活动安排_区间贪心_C++_Java

目录 牛客_AB31活动安排_区间贪心 题目解析 C代码 Java代码 牛客_AB31活动安排_区间贪心 活动安排_牛客题霸_牛客网 描述&#xff1a; 给定n个活动&#xff0c;每个活动安排的时间为[ai,bi)。求最多可以选择多少个活动&#xff0c;满足选择的活动时间两两之间没有重合。 …

购物车-多元素组合动画css

学习 渡一课程 多元素组合动画 练习。 在我们开发购物车功能时&#xff0c;经常会有点击添加按钮&#xff0c;就会有一个小圆点掉进购物车的动画&#xff0c;如下图所示&#xff0c;今天我们通过css来实现。 首先实现多元素组合动画 直接上代码&#xff0c;可以复制到本地使用…

深度学习:bert模型

multi-headed机制 1、通过不同的head得到多个特征表达&#xff0c;一般8个head 2、将所有特征拼接在一起 3、降维&#xff0c;将Z0~Z7连接一个FC全连接实现降维 多层堆叠 位置编码 如何实现位置编码&#xff1f; &#xff08;1&#xff09;为每个时间步添加一个0-1范围内的数…

Android Glide动态apply centerCropTransform(),transition withCrossFade动画,Kotlin

Android Glide动态apply centerCropTransform(),transition withCrossFade动画,Kotlin import android.graphics.Bitmap import android.os.Bundle import android.widget.ImageView import androidx.appcompat.app.AppCompatActivity import com.bumptech.glide.Glide import …

Vue 组件通信-自定义事件(七)

一、组件自定事件概念 自己定义的事件&#xff0c;包含事件名&#xff0c;事件回调等&#xff0c;定义好之后去给组件使用。也是一种组件的通信方式&#xff0c;适用于子组件传递给父组件。 二、 组件自定义事件实现子传父 1、在父组件中给子组件绑定一个自定义事件 在子组件标…

计算机的错误计算(一百四十八)

摘要 本节探讨 MATLAB 中 附近数的正割函数与 附近数的余割函数的计算精度问题。 例1. 已知 计算 直接贴图吧&#xff1a; 另外&#xff0c;16位的正确值分别为 0.4105556037464873e9、0.3670813182326778e13、-0.2549029285657875e8 与 -0.1248777628817462e12&am…

《XGBoost算法的原理推导》12-14决策树复杂度的正则化项 公式解析

本文是将文章《XGBoost算法的原理推导》中的公式单独拿出来做一个详细的解析&#xff0c;便于初学者更好的理解。 我们定义一颗树的复杂度 Ω Ω Ω&#xff0c;它由两部分组成&#xff1a; 叶子结点的数量&#xff1b;叶子结点权重向量的 L 2 L2 L2范数&#xff1b; 公式(…

算法练习:1004. 最大连续1的个数 III

题目链接&#xff1a;1004. 最大连续1的个数 III。 题目要求&#xff0c;给定一个数组&#xff0c;这个数组里面只有0或1&#xff0c;然后计算有多少个连续的1的最大长度&#xff0c;同时给了一个条件就是&#xff0c;可以把k个0变成1&#xff0c;然后来计算长度。 暴力解法&a…

CCS下载安装(以12.3.0版本为例)

Code Composer Studio 是一个集成开发环境 (IDE)&#xff0c;简称CCS软件。支持 TI 的微控制器和嵌入式处理器产品的开发。Code Composer Studio 包含一整套用于开发和调试嵌入式应用程序的工具。 CCS9.3.0及以上版本不需要License文件&#xff0c;但是CCS旧版本比如CCS5.5.0需…

串口接收,不定长数据接收

###1.CUBE-MX配置串口 2.我采用串口中断接收&#xff0c;打开中断接口 3.时钟同样8倍频&#xff0c;1分频&#xff0c;使用内部时钟 打开串口中断 main() { __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); // 启用空闲中断__HAL_UART_ENABLE_IT(&huart1, UART_IT_R…