【Netty+WebSocket详解】WebSocket全双工通信与Netty的高效结合与实战

一、 Netty网络框架、WebSocket协议基础

        1.1 Netty网络框架介绍

        1.2 WebSocket简介

        1.3 WebSocket握手流程

二、为什么选择Netty+WebSocket?

三、Netty+WebSocket与Spring WebSocket

        3.1 架构层级对比

        3.2 核心组件差异

        3.3 协议支持深度

        3.4 性能基准测试

        3.5 开发效率对比

        3.6 典型应用场景

        3.7 集成生态对比​编辑

四、基于Netty+WebSocket构建高性能实时通信系统

        4.1 技术选型

        4.2 pom.xml核心依赖

        4.3 Netty服务的启动类(服务器)

        4.4 WebSocket初始化器

        4.5 心跳处理类

        4.6 消息处理器

        4.7 Vue2 WebSocket连接核心代码

五、总结


一、 Netty网络框架、WebSocket协议基础

1.1 Netty网络框架介绍

参考我的另一篇文章:【Netty框架全解析】:从基础概念到高阶实践,从零玩转高性能网络框架!-CSDN博客

1.2 WebSocket简介

WebSocket是一种在单个TCP连接上进行全双工通信的协议,解决了HTTP协议的半双工和轮询效率低的问题。其核心特点:

全双工:客户端和服务端可同时发送数据。

持久连接:一次握手后保持长连接。

低延迟:无需频繁建立连接。

1.3 WebSocket握手流程

客户端发起HTTP请求:包含Upgrade:websocket头。

服务端响应101状态码:表示协议切换成功。

数据帧传输:后续通信通过二进制帧(Frame)进行。

握手请求示例

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Version: 13

握手响应示例

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=

二、为什么选择Netty+WebSocket?

在实时通信(IM)场景中,低延迟、高并发、长连接是核心需求。Netty作为高性能网络框架,结合WebSocket协议,能够完美满足这些要求:

全双工通信:WebSocket支持服务端主动推送,告别HTTP轮询

低延迟:Netty的Reactor线程模型+零拷贝技术,轻松支撑10万级并发

协议灵活:可扩展支持自定义二进制协议

本文将带你从零开始实现一个完整的IM系统,涵盖消息收发、用户在线状态管理、心跳检测等核心功能,并提供可运行的完整代码

三、Netty+WebSocket与Spring WebSocket

3.1 架构层级对比

3.2 核心组件差异

Netty核心模块

// 典型Netty WebSocket配置
pipeline.addLast(new HttpServerCodec()); // HTTP编解码
pipeline.addLast(new HttpObjectAggregator(65536)); // 聚合HTTP请求
pipeline.addLast(new WebSocketServerProtocolHandler("/ws")); // 协议升级
pipeline.addLast(new CustomFrameHandler()); // 自定义业务处理

Spring核心模块

// 典型Spring配置
@Configuration
@EnableWebSocket
public class Config implements WebSocketConfigurer {void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {registry.addHandler(myHandler(), "/ws");}
}

3.3 协议支持深度

3.4 性能基准测试

3.5 开发效率对比

3.6 典型应用场景

Netty更适合

游戏服务器(需要自定义二进制协议)

金融级交易系统(微秒级延迟要求)

IoT设备接入(海量长连接管理)

Spring WebSocket更适合

企业级消息通知系统

实时协作应用(如在线文档)

需要快速集成Spring Security的场景

3.7 集成生态对比

四、基于Netty+WebSocket构建高性能实时通信系统

4.1 技术选型

Java 8+、Netty 4.x、WebSocket协议、Maven

4.2 pom.xml核心依赖

<dependencies><dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.86.Final</version></dependency>
</dependencies>

4.3 Netty服务的启动类(服务器)

/*** ChatServer: Netty 服务的启动类(服务器)*/
public class ChatServer {public static void main(String[] args) throws Exception {// 定义主从线程组// 定义主线程池,用于接受客户端的连接,但是不做任何处理,比如老板会谈业务,拉到业务就会交给下面的员工去做了EventLoopGroup bossGroup = new NioEventLoopGroup();// 定义从线程池,处理主线程池交过来的任务,公司业务员开展业务,完成老板交代的任务EventLoopGroup workerGroup = new NioEventLoopGroup();try {// 构建Netty服务器ServerBootstrap server = new ServerBootstrap();     // 服务的启动类server.group(bossGroup, workerGroup)                // 把主从线程池组放入到启动类中.channel(NioServerSocketChannel.class)      // 设置Nio的双向通道.childHandler(new WSServerInitializer());   // 设置处理器,用于处理workerGroup// 启动server,并且绑定端口号875,同时启动方式为"同步"ChannelFuture channelFuture = server.bind(875).sync();// 请求:http://127.0.0.1:875// 监听关闭的channelchannelFuture.channel().closeFuture().sync();} finally {// 优雅的关闭线程池组bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}}

4.4 WebSocket初始化器

/*** 初始化器,channel注册后,会执行里面的相应的初始化方法*/
public class WSServerInitializer extends ChannelInitializer<SocketChannel> {@Overrideprotected void initChannel(SocketChannel channel) throws Exception {// 通过SocketChannel获得对应的管道ChannelPipeline pipeline = channel.pipeline();/*** 通过管道,添加handler处理器*/// HttpServerCodec 是由netty自己提供的助手类,此处可以理解为管道中的拦截器// 当请求到服务端,我们需要进行做解码,相应到客户端做编码// websocket 基于http协议,所以需要有http的编解码器pipeline.addLast(new HttpServerCodec());// 添加对大数据流的支持pipeline.addLast(new ChunkedWriteHandler());// 对httpMessage进行聚合,聚合成为FullHttpRequest或FullHttpResponse// 几乎在netty的编程中,都会使用到此handlerpipeline.addLast(new HttpObjectAggregator(1024 * 64));// ==================== 以上是用于支持http协议相关的handler ====================// ==================== 增加心跳支持 start ====================// 针对客户端,如果在5小时没有向服务端发送读写心跳(ALL),则主动断开连接// 如果是读空闲或者写空间,不做任何处理(参数分别对应读空闲、写空闲、读写空闲秒数)pipeline.addLast(new IdleStateHandler(8,10,300 * 60));pipeline.addLast(new HeartBeatHandler());// ==================== 增加心跳支持 end ====================// ==================== 以下是用于支持websocket ====================/*** WebSocket 服务器处理的协议,用于指定给客户端连接的时候访问路由: /ws* 此Handler会帮我们处理一些比较复杂的繁重的操作* 会处理一些握手操作:handShaking(close,ping,pong)ping + pong = 心跳* 对于WebSocket来说,数据都是以frames(帧)进行传输的,不同的数据类型所对应的frames(帧)也都不同*/pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));// 添加自定义的助手类pipeline.addLast(new ChatHandler());}
}

4.5 心跳处理类

/*** 创建心跳助手类*/
public class HeartBeatHandler extends ChannelInboundHandlerAdapter {@Overridepublic void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {// 判断evt是否是IdleStateEvent(空闲事件状态,包含 读空闲/写空闲/读写空闲)if (evt instanceof IdleStateEvent) {IdleStateEvent event = (IdleStateEvent)evt;if (event.state() == IdleState.READER_IDLE) {// System.out.println("进入读空闲...");} else if (event.state() == IdleState.WRITER_IDLE) {// System.out.println("进入写空闲...");} else if (event.state() == IdleState.ALL_IDLE) {Channel channel = ctx.channel();// 关闭无用的channel,以防资源浪费channel.close();}}}
}

4.6 消息处理器

/*** 创建自定义助手类*/
// SimpleChannelInboundHandler: 对于请求来说,相当于入站(入境)
// TextWebSocketFrame: 用于为websocket专门处理的文本数据对象,Frame是数据(消息)的载体
public class ChatHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {// 存储所有连接的Channelprivate static final ChannelGroup clients = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);@Overridepublic void channelActive(ChannelHandlerContext ctx) {clients.add(ctx.channel());System.out.println("客户端连接: " + ctx.channel().id());}@Overridepublic void channelInactive(ChannelHandlerContext ctx) {clients.remove(ctx.channel());System.out.println("客户端断开: " + ctx.channel().id());}@Overrideprotected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame frame) {String msg = frame.text();System.out.println("收到消息: " + msg);// 方案1:广播给所有客户端clients.writeAndFlush(new TextWebSocketFrame("[广播] " + msg));// 方案2:转发给特定客户端(示例逻辑)if (msg.startsWith("@")) {forwardToTargetClient(msg);}}private void forwardToTargetClient(String msg) {String targetId = msg.substring(1, msg.indexOf(" "));String content = msg.substring(msg.indexOf(" ") + 1);clients.stream().filter(ch -> ch.id().asShortText().equals(targetId)).findFirst().ifPresent(ch -> ch.writeAndFlush(new TextWebSocketFrame("[私信] " + content)));}/*** 发生异常并且捕获,移除channel*/@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {clients.remove(ctx.channel());ctx.close();cause.printStackTrace();}
}

4.7 Vue2 WebSocket连接核心代码

// src/utils/websocket.js
export default class SocketService {static instance = nullstatic get Instance() {if (!this.instance) {this.instance = new SocketService()}return this.instance}// 连接状态标记connected = falsews = null// 初始化连接connect() {if (!this.connected) {this.ws = new WebSocket('ws://localhost:875')this.ws.onopen = () => {this.connected = trueconsole.log('Netty连接成功')}this.ws.onmessage = (msg) => {console.log('收到消息:', msg.data)// 这里可以触发Vuex的action处理消息}this.ws.onclose = () => {this.connected = falseconsole.log('Netty连接关闭')}this.ws.onerror = (err) => {console.error('连接错误:', err)}}}// 发送消息send(data) {if (this.connected) {this.ws.send(JSON.stringify(data))} else {console.error('尚未建立连接')}}
}
<template><div><button @click="connect">连接Netty</button><button @click="sendTestMsg">发送测试消息</button><div v-for="(msg, index) in messages" :key="index">{{ msg }}</div></div>
</template><script>
import SocketService from '@/utils/websocket'export default {data() {return {messages: []}},methods: {connect() {SocketService.Instance.connect()},sendTestMsg() {SocketService.Instance.send({type: 'test',content: 'Hello Netty!',timestamp: Date.now()})}},mounted() {// 可选:组件加载时自动连接// this.connect()}
}
</script>

4.8 Spring WebSocket实现简单通信系统

参考我的文章:【Spring WebSocket详解】Spring WebSocket从入门到实战-CSDN博客

五、总结

本文通过Netty框架实现了基于WebSocket协议的简单通信系统,覆盖了从基础握手、消息处理到心跳检测的全流程。实际开发中还需考虑安全性(如WSS加密)、跨域处理、消息持久化等高级功能。如果你对上文有什么其他理解或者问题欢迎评论区留言讨论!

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

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

相关文章

5、Vue中使用Cesium实现交互式折线绘制详解

引言 Cesium是一款强大的开源3D地理信息可视化引擎&#xff0c;广泛应用于数字地球、地图可视化等领域。在Vue项目中集成Cesium可以快速构建高性能的地理信息应用。本文将详细介绍如何在Vue项目中实现交互式折线绘制功能&#xff0c;包括顶点添加、临时绘制、距离计算等核心功…

mysql实战之主从复制

原理图理论&#xff1a;一、配置准备每台主机都安装mysql对每台主机都进行对时操作&#xff0c;减少时间误差[rooteveryone ~]# timedatectl set-timezone Asia/Shanghai [rooteveryone ~]# systemctl restart chronyd.service 对每台主机都进行关闭防火墙、上下文等&#xff0…

中望CAD2026亮点速递(5):【相似查找】高效自动化识别定位

本文为CAD芯智库整理&#xff0c;未经允许请勿复制、转载&#xff01;原文转自&#xff1a;www.xwzsoft.com/h-nd-594.html CAD的相似查找功能主要应用于需要重复操作、标准化控制、一致性检查或复杂模式识别的场景&#xff0c;通过图形相似度算法&#xff0c;快速找到匹配的图…

国产化条码类库Spire.Barcode教程:使用 C# 读取二维码(QR Code)——从图片或数据流解析

二维码已成为现代应用的常见组成部分&#xff0c;广泛应用于用户身份验证、移动支付、商品包装和活动票务等场景。很多使用 C# 开发的系统需要从图像或扫描件中提取二维码信息&#xff0c;因此掌握二维码识别技术显得尤为重要。 为满足这类需求&#xff0c;开发者需要一种既可…

IPSAN 共享存储详解:架构、优化与落地实践指南

一、IPSAN 技术定位与核心价值核心价值对比矩阵&#xff1a;维度IPSANFC-SAN实现方案成本端口成本$500端口成本$2000复用IP网络设备传输距离跨地域&#xff08;VPN/专线&#xff09;≤10公里两地三中心架构运维效率SNMP/CLI管理Zone/ALPA管理自动化运维工具链协议标准IETF RFC …

【卫星语音】基于神经网络的低码率语音编解码(ULBC)方案架构分析:以SoundStream为例

摘要 随着深度学习技术的快速发展&#xff0c;基于神经网络的音频编解码技术已成为下一代音频压缩的重要研究方向。本文以Google提出的SoundStream为核心分析对象&#xff0c;深入探讨其在低码率语音编解码领域的创新架构设计和关键技术突破。SoundStream通过全卷积编解码器网络…

技术面试问题总结一

MySQL的几种锁机制一、从锁的粒度角度划分表级锁机制&#xff1a;它是对整张表进行锁定的一种锁。当一个事务对表执行写操作时&#xff0c;会获取写锁&#xff0c;在写锁持有期间&#xff0c;其他事务无法对该表进行读写操作&#xff1b;而当事务执行读操作时&#xff0c;会获取…

Python(一)

基本语法&#xff1a;变量&#xff0c;语法变量类型&#xff1a;不同于Java&#xff0c;C语言&#xff0c;C&#xff0c;Python在创建一个变量的时候&#xff0c;不需要声明变量类型&#xff0c;由编译器自行识别Python语句在只有一个语句的时候语句末尾不需要分号&#xff0c;…

Adaptive AUTOSAR中的Firewall技术:智能汽车网络安全架构的核心

1 防火墙技术基础 1.1 定义与演进历程 防火墙(Firewall)作为一种位于内部网络与外部网络之间的网络安全系统,本质上是依照特定规则允许或限制数据传输的信息安全防护机制。在汽车电子电气架构从分布式向集中式转变的背景下,防火墙技术已从传统的IT领域深度融入Adaptive A…

android闪光灯源码分析

目录 一、APP层源码分析 二&#xff0c;framework层代码分析 ​​​​​​​2.1 binder溯源 这几天撸了android11 aosp闪光灯源码&#xff0c;本着前人栽树后人乘凉的原则&#xff0c;有志于android系统开发的新同学们提供一盏明灯&#xff0c;照亮你们前行。 本人撸代码风格&…

文心一言4.5开源部署指南及文学领域测评

&#x1f4dd;个人主页&#xff1a;哈__ 期待您的关注 目录 一、引言 二、文心一言开源模型 2.1 MoE架构 2.2 文心一言MoE架构 三、文心一言稠密模型部署 3.1 产品选择 3.2 环境选择 3.3 Python3.12安装 3.3 PaddlePaddle-GPU安装 3.4 FastDeploy-GPU安装 ​编辑3.…

深入探讨 C++ 中的浮点数数据类型

核心概念&#xff1a;IEEE 754 标准 C 中的浮点数&#xff08;float, double, long double&#xff09;在绝大多数现代系统上遵循 IEEE 754 标准。这个标准定义了浮点数在内存中的二进制表示方式、运算规则、特殊值&#xff08;如无穷大、NaN&#xff09;等。数据类型与精度 fl…

相机:以鼠标点为中心缩放(使用OpenGL+QT开发三维CAD)

很多软件中&#xff08;Auto CAD、ODA等&#xff09;支持以鼠标点为中心进行放缩操作&#xff0c;有什么黑科技吗&#xff1f; 本章节为相机原理和实现的补充内容&#xff0c;支持鼠标放缩时以鼠标点为中心进行放缩。 对应视频课程已上线&#xff0c;欢迎观看和支持~ https:…

​​XAMPP安全升级指南:修复CVE-2024-4577漏洞,从PHP 8.2.12升级至PHP 8.4.10​​

​​1. 背景与漏洞概述​​ 近期,PHP官方披露了一个高危漏洞 ​​CVE-2024-4577​​,该漏洞影响PHP 8.2.x及更早版本,可能导致远程代码执行(RCE)或信息泄露。由于XAMPP默认捆绑的PHP版本(如8.2.12)可能受此漏洞影响,建议用户尽快升级至最新的​​PHP 8.4.10​​(或官…

ES 压缩包安装

以下是 Elasticsearch (ES) 通过 .tar.gz 压缩包安装的详细步骤&#xff08;适用于 Linux/macOS 系统&#xff09;&#xff1a; 1. 准备工作 1.1 检查系统依赖 Java 环境&#xff1a;ES 需要 JDK&#xff0c;推荐 OpenJDK 11/17&#xff08;ES 7.x/8.x 兼容版本&#xff09;。…

RoboRefer:面向机器人视觉-语言模型推理的空间参考

25年6月来自北航、北大和北京智源的论文“RoboRefer: Towards Spatial Referring with Reasoning in Vision-Language Models for Robotics”。 空间参考是实体机器人与三维物理世界交互的基本能力。然而&#xff0c;即使有了强大的预训练视觉-语言模型 (VLM)&#xff0c;近期方…

【Unity】MiniGame编辑器小游戏(十)连连看【Link】

更新日期:2025年7月9日。 项目源码:获取项目源码 索引 连连看【Link】一、游戏最终效果二、玩法简介三、正式开始1.定义游戏窗口类2.规划游戏窗口、视口区域3.方块 Block①.定义方块类②.生成方块所有类型③.生成连连看棋盘④.绘制方块阵列4.连线 Line①.点击方块连线②.尝试…

Enable ADB Debugging Before Connect

If you don’t enable Developer Options and turn on USB Debugging before plugging in the cable, adb devices won’t detect the phone because the Android system doesn’t trust the connection yet. Here’s what you need to do step-by-step to fix this:✅ 1. Enab…

从互联网电脑迁移Dify到内网部署Dify方法记录

一、在互联网电脑上准备迁移文件1. 保存 Docker 镜像# 获取所有 Dify 相关镜像&#xff08;根据实际容器名调整&#xff09; docker ps --filter "namedify" --format "{{.Image}}" | sort -u > dify-images.list# 保存镜像为 .tar 文件 docker save $(…

【EGSR2025】材质+扩散模型+神经网络相关论文整理随笔(一)

MatSwap: Light-aware material transfers in images介绍任务&#xff1a;输入一张拍摄图像、示例材质纹理图像&#xff08;这里跟BRDF无关&#xff0c;通常我们讲到材质一般指的是SVBRDF&#xff0c;但是这里的材质指的只是纹理&#xff09;、用户为拍摄图像指定的遮罩区域&am…