【Netty】实现IM聊天室案例Demo

news2024/10/7 20:36:15

文章目录

      • 1、WebSocket链接建立
      • 2、实现用户上线功能
      • 3、私聊发送消息

注意:

该文章不会详细介绍Netty相关概念和原理,主要目的是介绍如何快速构建聊天室Demo
不会在文章主体过多说明代码流程,文章中的代码已经配备了详细的注释

1、WebSocket链接建立

首先创建maven项目,引入相关依赖:

<dependencies>
    <!--Netty-->
    <dependency>
        <groupId>io.netty</groupId>
        <artifactId>netty-all</artifactId>
        <version>4.1.85.Final</version>
    </dependency>
    <!--Lombok-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.20</version>
    </dependency>
    <!--fastjson-->
    <dependency>
        <groupId>com.alibaba.fastjson2</groupId>
        <artifactId>fastjson2</artifactId>
        <version>2.0.18</version>
    </dependency>
</dependencies>

编写服务端代码,用于监听客户端发送的事件:

/**
 * @Author 徐志斌
 * @Date: 2023/1/17 20:06
 * @FileName: IMServer
 * @Description: 通过WebSocket进行通信,不使用HTTP进行数据通信
 */
public class IMServer {
    /**
     * 启动服务端
     */
    public static void start() {
        // 1.创建两个EventLoop组,用于处理不同的事件
        EventLoopGroup boss = new NioEventLoopGroup();
        EventLoopGroup worker = new NioEventLoopGroup();

        // 2.服务端处理流程
        ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap.group(boss, worker)
                .channel(NioServerSocketChannel.class) // 与客户端进行读写的数据通道channel
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel channel) throws Exception { // 连接建立后会调用该方法初始化
                        // pipeline流水线:管理服务端整体的处理流程
                        ChannelPipeline pipeline = channel.pipeline();
                        pipeline.addLast(new HttpServerCodec()) // HTTP编码器
                                .addLast(new ChunkedWriteHandler()) // 支持大数据流
                                .addLast(new HttpObjectAggregator(1024 * 64)) // 对HTTP消息进行聚合
                                .addLast(new WebSocketServerProtocolHandler("/")) // WebSocket协议
                                .addLast(new WebSocketHandler()); // 自定义处理器
                    }
                });

        // 3.监听8080端口
        ChannelFuture future = bootstrap.bind(8080);
    }
}

编写自定义处理器代码,将接收到的通信信息打印到控制台:

/**
 * @Author 徐志斌
 * @Date: 2023/1/17 20:16
 * @FileName: WebSocketHandler
 * @Description: 
 */
public class WebSocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
    
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame frame) throws Exception {
        System.out.println(frame.text());
    }
}

最后,使用Main方法调用IMServer.start()启动,监听8080端口,等待客户端发送数据

本次案例不通过HTTP协议进行通信,使用WebSocket协议,可以通过浏览器访问:http://websocket-test.com/,通过该网页为我们的服务端发送数据,效果如下,说明连接建立成功!

在这里插入图片描述
控制台信息:
在这里插入图片描述

2、实现用户上线功能

在IMServer中,加入ConcurrentHashMap,用于存放上线后的用户信息:

// 与服务端连接成功的用户存放到该Map中
public static final Map<String, Channel> USERS = new ConcurrentHashMap<>();

调整自定义事件中的代码,监听连接事件

public class WebSocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame frame) throws Exception {
        try {
            // 解析客户端发送的消息,类中数据根据实际事件信息进行封装
            Command command = JSON.parseObject(frame.text(), Command.class);

            // 判断事件类型,不同事件类型不同处理方式
            switch (command.getCode()) {
                case "连接事件":
                    ConnectionHandler.execute(ctx, command); // 客户端发送的是建立连接事件
                default:
                    ctx.channel().writeAndFlush("不支持该事件");
            }
        } catch (Exception e) {
            ctx.channel().writeAndFlush(e);
        }
    }
}

连接事件处理类:

public class ConnectionHandler {
    /**
     * 建立连接
     */
    public static void execute(ChannelHandlerContext ctx, Command command) {
        // 如果已经连接过,就不能进行连接了
        if (IMServer.USERS.containsKey(command.getNickName())) {
            ctx.channel().writeAndFlush("该用户已上线");
            ctx.channel().disconnect();
            return;
        }
        // 连接后,将用户信息存入IMServer的Map中
        IMServer.USERS.put(command.getNickName(), ctx.channel());
        // 提示客户端,连接成功
        ctx.channel().writeAndFlush("系统消息:与服务端建立连接成功");
    }
}

3、私聊发送消息

调整自定义事件中的代码,让其支持发送消息事件:

public class WebSocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame frame) throws Exception {
        try {
            // 解析客户端发送的消息,类中数据根据实际事件信息进行封装
            Command command = JSON.parseObject(frame.text(), Command.class);

            // 判断事件类型,不同事件类型不同处理方式
            switch (command.getCode()) {
                case "连接事件":
                    ConnectionHandler.execute(ctx, command); // 客户端发送的是建立连接事件
                case "私发信息":
                    ChatHandler.execute(ctx,frame); // 客户端发送的是发现消息事件
                default:
                    ctx.channel().writeAndFlush("不支持该事件");
            }
        } catch (Exception e) {
            ctx.channel().writeAndFlush(e);
        }
    }
}

编写发送消息事件处理类代码:

public class ChatHandler {
    public static void execute(ChannelHandlerContext ctx, TextWebSocketFrame frame) {
        try {
            // 将消息格式转成规定好的(不同场景,格式不同)
            ChatMessage chat = JSON.parseObject(frame.text(), ChatMessage.class);
            // 获取消息接受方
            Channel channel = IMServer.USERS.get(chat.getTarget());
            // 消息发送给接收方
            channel.writeAndFlush(chat.getContent());
        } catch (Exception e) {
            ctx.channel().writeAndFlush("发送消息格式错误,请确认后尝试");
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网站建设 之 用js写wasm

为什么要这么做&#xff1f;编译js比解释js更快是必然的wasm是什么&#xff1f;我期望是一个二进制文件WebAssembly&#xff08;又名wasm&#xff09;是一种高效的&#xff0c;低级别的编程语言。 它让我们能够使用JavaScript以外的语言&#xff08;例如C&#xff0c;C &#x…

【Linux】进度条小程序

目录一.\r && \n二.行缓存区概念问题&#xff1a;解答&#xff1a;检测&#xff1a;三.进度条1.进度动态条2.进度百分比3.小装饰4.颜色该篇博客会主要按步骤推导出一个在Linux上运行的进度条小程序&#xff0c;会用到vim编辑器和gcc编译器&#xff0c;如果对这两个软件…

Centos7安装、卸载nginx及配置,配置成系统服务(一步到位)

目录 前言 一、下载安装解压 1.进入临时文件夹里&#xff08;随便一个都行&#xff09; 2.下载并安装nginx压缩包 3.解压该压缩包 4.创建目标文件夹 5.&#xff08;默认会安装在/usr/local/nginx&#xff09;这里通过configure命令指定安装目录 6.编译安装 7.最后生成的…

一、初始Numpy

1、numpy简介 简介 Numpy&#xff08;Numerical Python&#xff09;是Python语言的一个扩展程序库&#xff0c;支持大量的维度数组与矩阵运算&#xff0c;此外也针对数组运算提供大量的数学函数库 Numpy的前身Numeric最早是有Jim Hugunin与其他协作者共同开发&#xff0c;20…

十五天学会Autodesk Inventor,看完这一系列就够了(九),主题/色彩/单位设置

众所周知&#xff0c;Autocad是一款用于二维绘图、详细绘制、设计文档和基本三维设计&#xff0c;现已经成为国际上广为流行的绘图工具。Autodesk Inventor软件也是美国AutoDesk公司推出的三维可视化实体模拟软件。因为很多人都熟悉Autocad&#xff0c;所以再学习Inventor&…

使用SpringBoot创建web项目,并使用外部Tomcat

使用SpringBoot创建web项目&#xff0c;并使用外部Tomcat 目录使用SpringBoot创建web项目&#xff0c;并使用外部Tomcat简单介绍&#xff1a;特点&#xff1a;步骤简介下面就使用SpringBoot创建一个web工程&#xff0c;并且使用外部的Tomcat和实现对jsp的支持&#xff1a;一、创…

AIDL 应用间简单通信demo及基本问题

AIDL:Android Interface Definition Language,即Android接口定义语言。 他的作用大家已经知道了&#xff0c;有些童鞋对于其中的使用细节可能会有一些理解误差&#xff0c;并且会造成一写异常或者通讯失败。 我们先看几个关键点再看代码&#xff0c;如果项目不符合这几点&…

ffmpeg编译android平台-(ubuntu+ndkr16b+ffmpeg3.4.12)

一、环境配置 1、下载NDK,NDK老版本 1.1、 ubuntu下载 wget https://dl.google.com/android/repository/android-ndk-r16b-linux-x86_64.zip1.2、解压NDK unzip android-ndk-r16b-linux-x86_64.zip1.3、配置NDK环境变量 vim /etc/profile1.4、 在profile文件中添加如下内容…

String.prototype.matchAll called with a non-global RegExp argument

如上 matchAll这个API 与 正则的全局匹配是不一样的。他会将匹配到的所有字符串以迭代器的形式返回出来。 我们可以使用Array.from或者数据解构来获得匹配到的数组。 他与正则全局匹配的区别是当正则表达式包含()捕获组的时候&#xff0c;全局匹配无法获得子匹配组的数据。 …

【Datewhale一起吃瓜 Task1】周志华西瓜书第一章+第二章

这里写目录标题机器学习是干什么的机器学习的理论基础: PAC模型基本术语关于数据关于假设关于模型训练机器学习任务分类归纳偏好模型的评估和选择训练流程划分数据集的方法留出法交叉验证自助法性能度量机器学习是干什么的 我们目前处于大数据时代&#xff0c;每天会产生数以亿…

一个监控系统的典型架构是什么样的

典型架构 采集器是负责采集监控数据的,采集到数据之后传输给服务端,通常是直接写入时序库。然后就是对时序库的数据进行分析和可视化,分析部分最典型的就是告警规则判断(复杂一些的会引入统计算法和机器学习的能力做预判),即图上的告警引擎,告警引擎产生告警事件之后交给…

华为MPLS跨域带RR实验配置

目录 Option B方案实验配置 配置建立Vpnv4邻居 配置反射器 配置RR和ASBR取消RT值检测 配置ASBR相连接口开启MPLS 配置ASBR向RR发送路由时更改下一跳 Option C1方案实验配置 Option C2方案实验配置 接口IP地址、底层IGP路由协议&#xff08;ISIS&#xff09;、MPLS LDP协…

一种环状二肽3705-26-8,cyclo(Pro-Phe),环(PHE-PRO)环状二肽

基础产品数据&#xff08;Basic Product Data&#xff09;&#xff1a;CAS号&#xff1a;3705-26-8中文名&#xff1a;环(PHE-PRO)英文名&#xff1a;cyclo(Pro-Phe)&#xff0c;CYCLO(-PHE-PRO)结构式&#xff08;Structural&#xff09;&#xff1a;详细产品数据&#xff08;…

qq消息撤回

开发工具 工具名称工具类型说明AndroidStuduo编辑工具开发工具jadxjava工具将apk解成java项目xposed插件工具插件qq版本8.8.80 开始 先通过jadx把apk反编译出来源码&#xff0c;通过build出来&#xff0c;在android studio打开&#xff0c;方便分析。 要撤回自己的消息&…

TMC步进电机驱动stealthChop

一直觉得tmc系列的芯片功能很强大&#xff0c;但是我自己读寄存器手册的感觉就是每个字我都认识&#xff0c;怎么就这么难懂。。。。 stealthChop 是一种电压控制技术&#xff0c;基于电压斩波器的工作远离&#xff0c;可在低速中速范围内以最大扭矩实现绝对静音的步进电机控制…

【推荐】自用软件工具推荐 WIN

一、图片查看器 Honeyview 蜂蜜浏览器 免费的图像查看器 下载和功能说明 (bandisoft.com) 轻量而快速可以显示包括 GPS 信息在内的 JPEG 格式的 EXIF 信息对图像格式进行批量转换和调整大小支持显示 GIF 和 WebP 动图无需解压即可直接查看压缩包中的图像支持的格式 图像格式…

大厂整个项目的开发规范流程

第1节、大厂码农开发基础 内容 本章节给大家介绍在互联网做开发&#xff0c;基础环境、开发技术以及上线和监控都会用到哪些东西。一般互联网大厂像阿里、京东、腾讯等都会有公司自研的一些技术组件&#xff0c;比如&#xff1a;RPC、MQ、数据库路由等&#xff0c;但所有的这些…

API 网关的功能用途及实现方式

1. API 网关诞生背景 前言 API 经济生态链已经在全球范围覆盖&#xff0c; 绝大多数企业都已经走在数字化转型的道路上&#xff0c;API 成为企业连接业务的核心载体&#xff0c; 并产生巨大的盈利空间。快速增长的 API 规模以及调用量&#xff0c;使得企业 IT 在架构上、模式…

flume整合数据到kafka,sparkStreaming消费数据,并存储到hbase和redis中

目录 1、模拟数据生成 2、flume采集数据 1、node01配置flume的conf文件 2、node02开发flume的配置文件 3、node03开发flume的配置文件 4、开发flume启动停止脚本 5、node01执行以下命令创建kafka的topic 6、启动并查看kafka的数据 3、SparkStreaming消费kafka中的数…

第二章.线性回归以及非线性回归—LASSO算法

第二章.线性回归以及非线性回归 2.13 LASSO算法 1.前期导入&#xff1a; 通过构造一个一阶惩罚函数获得一个精炼的模型&#xff1b;通过最终确定一些指标(变量)的系数为零&#xff0c;解释力很强 岭回归估计系数等于0的机会微乎其微&#xff0c;造成筛选变量困难 擅长处理具有…