目录

    • 一、WebSocket:实时通信的"高速公路"
      • 1.1 HTTP的短板:永远的"单相思"
      • 1.2 WebSocket的优势:真正的"双向对话"
    • 二、30分钟搭建聊天服务器
      • 2.1 环境准备
      • 2.2 WebSocket配置类
      • 2.3 核心消息处理器
    • 三、前端实现:比AJAX简单多了!
      • 3.1 HTML骨架
    • 四、进阶功能:让聊天室更专业
      • 4.1 用户认证(带Token的连接)
      • 4.2 私聊功能
      • 4.3 在线用户列表
    • 五、性能优化:应对高并发场景
      • 5.1 二进制消息传输(适合传输文件)
      • 5.2 心跳检测(防止连接假死)
    • 六、生产环境注意事项
      • 6.1 负载均衡:需要支持WebSocket的LB(如Nginx)
      • 6.2 SSL安全:务必使用WSS
      • 6.3 连接管理:实现重连机制
      • 6.4 消息压缩:减少带宽消耗
    • 七、WebSocket的替代方案
    • 八、常见问题排雷
    • 结语:从聊天室到实时世界的桥梁

“为什么我的页面要不停刷新才能看到新消息?” —— 如果你还在为这种用户体验头疼,那么WebSocket就是你的解药!今天,我要带你用WebSocket打造一个真正的实时聊天应用,告别落后的轮询时代,体验丝滑般的即时通讯。

一、WebSocket:实时通信的"高速公路"

1.1 HTTP的短板:永远的"单相思"

传统HTTP就像写信交流:

  • 客户端:“有新消息吗?”(请求)
  • 服务器:“没有”(响应)
  • (重复100次…)
  • 客户端:“有新消息吗?”
  • 服务器:“有!”(终于等到你)

这种轮询(Polling)方式不仅低效,还浪费资源!

1.2 WebSocket的优势:真正的"双向对话"

WebSocket建立了持久化的全双工通道:

  • 一次握手,长久连接
  • 服务器可以主动推送
  • 低延迟,高效能
  • 节省带宽(无需重复HTTP头)

二、30分钟搭建聊天服务器

2.1 环境准备

# 使用Spring Boot快速启动
spring init --dependencies=websocket,lombok websocket-chat

2.2 WebSocket配置类


@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {registry.addHandler(chatHandler(), "/chat").setAllowedOrigins("*"); // 允许跨域}@Beanpublic WebSocketHandler chatHandler() {return new ChatWebSocketHandler();}
}

2.3 核心消息处理器

public class ChatWebSocketHandler extends TextWebSocketHandler {private static final List<WebSocketSession> sessions = new CopyOnWriteArrayList<>();@Overridepublic void afterConnectionEstablished(WebSocketSession session) {sessions.add(session);broadcast("系统: " + session.getId() + " 加入聊天室");}@Overrideprotected void handleTextMessage(WebSocketSession session, TextMessage message) {String msg = session.getId() + ": " + message.getPayload();broadcast(msg);}@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus status) {sessions.remove(session);broadcast("系统: " + session.getId() + " 离开聊天室");}private void broadcast(String message) {sessions.forEach(session -> {try {session.sendMessage(new TextMessage(message));} catch (IOException e) {e.printStackTrace();}});}
}

三、前端实现:比AJAX简单多了!

3.1 HTML骨架

<!DOCTYPE html>
<html>
<head><title>实时聊天室</title><style>#chatBox {height: 300px;border: 1px solid #ccc;overflow-y: scroll;}#msgInput {width: 80%;}</style>
</head>
<body>
<div id="chatBox"></div>
<input id="msgInput" type="text" placeholder="输入消息...">
<button onclick="sendMessage()">发送</button><script>const chatBox = document.getElementById('chatBox');const msgInput = document.getElementById('msgInput');let socket;function connect() {socket = new WebSocket('ws://' + window.location.host + '/chat');socket.onopen = () => appendMessage('系统: 连接已建立');socket.onmessage = (event) => appendMessage(event.data);socket.onclose = () => appendMessage('系统: 连接已关闭');}function sendMessage() {if (socket && msgInput.value) {socket.send(msgInput.value);msgInput.value = '';}}function appendMessage(message) {const p = document.createElement('p');p.textContent = message;chatBox.appendChild(p);chatBox.scrollTop = chatBox.scrollHeight;}// 页面加载时自动连接window.onload = connect;
</script>
</body>
</html>

四、进阶功能:让聊天室更专业

4.1 用户认证(带Token的连接)

后端改造:


@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {registry.addHandler(chatHandler(), "/chat").setAllowedOrigins("*").addInterceptors(new AuthHandshakeInterceptor());
}public class AuthHandshakeInterceptor implements HandshakeInterceptor {@Overridepublic boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) {String token = ((ServletServerHttpRequest) request).getServletRequest().getParameter("token");return validateToken(token); // 实现你的验证逻辑}// ... afterHandshake方法
}

前端连接:

socket = new WebSocket(`ws://${window.location.host}/chat?token=${userToken}`);

4.2 私聊功能

消息格式改造:

{"type": "private","target": "user123","content": "晚上一起吃饭?"
}

后端处理:


@Getter
@Setter
class ChatMessage {private String type;private String from;private String target;private String content;
}// 在Handler中
private void handleJsonMessage(WebSocketSession session, String json) {ChatMessage msg = objectMapper.readValue(json, ChatMessage.class);if ("private".equals(msg.getType())) {sendToUser(msg.getTarget(), msg.getFrom() + "(私信): " + msg.getContent());}// ... 其他类型处理
}

4.3 在线用户列表

后端实现:

private static final Map<String, WebSocketSession> userSessions = new ConcurrentHashMap<>();@Override
public void afterConnectionEstablished(WebSocketSession session) {String username = getUsernameFromSession(session);userSessions.put(username, session);broadcastUserList();
}private void broadcastUserList() {String userList = objectMapper.writeValueAsString(userSessions.keySet());broadcast("USER_LIST:" + userList);
}

前端展示:

socket.onmessage = (event) => {if (event.data.startsWith('USER_LIST:')) {updateUserList(JSON.parse(event.data.substring(10)));} else {appendMessage(event.data);}
};

五、性能优化:应对高并发场景

5.1 二进制消息传输(适合传输文件)

// 二进制处理器
public class BinaryWebSocketHandler extends BinaryWebSocketHandler {@Overrideprotected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) {byte[] payload = message.getPayload().array();// 处理二进制数据(如图片、文件)}
}// 前端发送
const fileReader = new FileReader();
fileReader.onload = () => {socket.send(fileReader.result);
};
fileReader.readAsArrayBuffer(file);

5.2 心跳检测(防止连接假死)

// 心跳处理器
public class HeartbeatWebSocketHandler extends TextWebSocketHandler {@Overrideprotected void handleTextMessage(WebSocketSession session, TextMessage message) {if ("PING".equals(message.getPayload())) {session.sendMessage(new TextMessage("PONG"));}// ... 其他消息处理}
}// 前端定时发送
setInterval(() => {if (socket.readyState === WebSocket.OPEN) {socket.send("PING");}
}, 30000);

六、生产环境注意事项

6.1 负载均衡:需要支持WebSocket的LB(如Nginx)

location /chat {proxy_pass http://backend;proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "upgrade";
}

6.2 SSL安全:务必使用WSS

new WebSocket('wss://yourdomain.com/chat');

6.3 连接管理:实现重连机制

function connect() {socket = new WebSocket(...);socket.onclose = () => setTimeout(connect, 5000); // 5秒后重连
}

6.4 消息压缩:减少带宽消耗

config.setCompressionEnabled(true); // 服务端启用压缩

七、WebSocket的替代方案

技术优点缺点
SSE服务器单向推送简单不支持双向通信
长轮询兼容性极好高延迟,高开销
MQTT轻量级,适合IoT需要额外Broker
gRPC高性能,支持流式通信复杂度高

八、常见问题排雷

Q:为什么我的连接经常断开?

A:检查:

  • 代理服务器超时设置(默认可能60秒)
  • 客户端没有正确处理心跳
  • 网络不稳定

Q:如何保证消息顺序?

A:WebSocket本身保证顺序,但要注意:

  • 避免多线程并发发送
  • 客户端使用队列处理

Q:能支持多少并发连接?

A:取决于:

  • 单机:Netty轻松支持10万+
  • 集群:需要合理设计架构

结语:从聊天室到实时世界的桥梁

通过本文,我们完成了:

  • 基础聊天室的搭建
  • 进阶功能开发
  • 性能优化技巧
  • 生产环境实践

动手时间:尝试为你的聊天室添加这些功能:

  • 消息已读回执
  • 聊天消息持久化
  • 发送图片/表情包

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

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

相关文章

宏集案例 | 基于CODESYS的自动化控制系统,开放架构 × 高度集成 × 远程运维

​​案例概况客户&#xff1a;MACS Sterilisationsanlagen GmbH&#xff08;Ermafa Environmental Technologies GmbH 旗下&#xff09; 应用场景&#xff1a;医疗与感染性废弃物的无害化处理控制系统应用产品&#xff1a;宏集Berghof高性能控制器设备&#xff08;一&#xff0…

学习JNI 二

创建一个名为Learn1项目&#xff08;Android Studio&#xff09;。一、项目结构二、配置 build.gradlebuild.gradle.kts(:app)plugins {alias(libs.plugins.android.application)alias(libs.plugins.jetbrains.kotlin.android) }android {namespace "com.demo.learn1&quo…

基于Spring Boot+Vue的DIY手工社预约管理系统(Echarts图形化、腾讯地图API)

2.10 视频课程管理功能实现2.11手工互动&#xff08;视频弹幕&#xff09;2.8预约设置管理功能实现&#x1f388;系统亮点&#xff1a;Echarts图形化、腾讯地图API&#xff1b;文档包含功能结构图、系统架构图、用例图、实体属性图、E-R图。一.系统开发工具与环境搭建1.系统设计…

leetcode 每日一题 1353. 最多可以参加的会议数目

更多技术访问 我的个人网站 &#xff08;免费服务器&#xff0c;没有80/443端口&#xff09; 1353. 最多可以参加的会议数目 给你一个数组 events&#xff0c;其中 events[i] [startDayi, endDayi] &#xff0c;表示会议 i 开始于 startDayi &#xff0c;结束于 endDayi 。 …

AI+智慧园区 | 事件处置自动化——大模型重构园区治理逻辑

在智慧园区的建设浪潮中&#xff0c;事件管理一直是园区高效运营的关键环节。考拉悠然所推出的大模型 智慧园区解决方案&#xff0c;在事件智能闭环管理方面独树一帜&#xff0c;为园区的日常运营编织了一张严密、高效、智能的管理网络&#xff0c;实现了从事件感知到处置的全…

FFmpeg Windows安装

FFmpeg 用于音频文件转换 Builds - CODEX FFMPEG gyan.dev ffmpeg-release-full.7z 下载完成之后 zip解压 大概就是 ffmpeg/ └── bin/ └── ffmpeg.exe 配置环境变量 ffmpeg -version 有可能idea还是找不到命令 就把命令路径写在程序里 例如

【2025/07/10】GitHub 今日热门项目

GitHub 今日热门项目 &#x1f680; 每日精选优质开源项目 | 发现优质开源项目&#xff0c;跟上技术发展趋势 &#x1f4cb; 报告概览 &#x1f4ca; 统计项&#x1f4c8; 数值&#x1f4dd; 说明&#x1f4c5; 报告日期2025-07-10 (周四)GitHub Trending 每日快照&#x1f55…

JVM 基础 - JVM 内存结构

前言 本文主要对JVM 内存结构进行讲解&#xff0c;注意不要和Java内存模型混淆了。 运行时数据区 内存是非常重要的系统资源&#xff0c;是硬盘和 CPU 的中间仓库及桥梁&#xff0c;承载着操作系统和应用程序的实时运行。JVM 内存布局规定了 Java 在运行过程中内存申请、分配…

【案例】二手车交易价格预测-472

二手车交易价格预测 数据来源数据特征探索构建模型参考数据来源 天池 https://tianchi.aliyun.com/competition/entrance/231784/information 数据特征探索 目标特征工程做好之后,能同时进行 lightgbm catboost 神经网络等模型,所以尽量都转换为数值类特征。 如果仅仅是使用…

【Spring】Java SPI机制及Spring Boot使用实例

目录 一、SPI是什么 1.1 SPI 和 API 有什么区别&#xff1f; 二、使用场景 三、使用介绍 四、Spring Boot实例运用 五、总结 一、SPI是什么 SPI全称Service Provider Interface&#xff0c;是Java提供的一套用来被第三方实现或者扩展的API&#xff0c;它可以用来启用框架…

多维度数据资产测绘技术在安全管控平台中的应用实践

一、数据资产治理困境&#xff1a;从 “黑箱” 到 “可见性” 的行业挑战在数字化转型加速的当下&#xff0c;企业数据资产呈现爆发式增长&#xff0c;而传统资产梳理手段因维度单一、时效性差&#xff0c;导致 “资产黑箱” 问题频发。某省级运营商曾在安全评估中发现&#xf…

搭建react18+项目过程中遇到的问题(vite)

问题1. 页面中使用import.meta.env获取环境变量有红色波浪线提示错误按提示给ts.config.ts文件中的compilerOptions增加了"module": “esnext” (es2020 | es2022 | system)这几个也不行 但是另一个问题出现了安装的第三方库引入报错了 按照提示我们将module改成了’…

Linux epoll简介与C++TCP服务器代码示例

Linux epoll 简介与示例 TCP 服务器 1. 为什么要用 epoll select/poll 每次调用都把全部文件描述符从用户态拷贝到内核态,随连接数增长而线性变慢;epoll 采用事件驱动+就绪队列的方式,内核只把“已就绪”的描述符返回给用户态,O(1) 规模扩展;支持 边沿触发 Edge-Triggere…

IPv4和IPv6双栈配置

根据IPv6的学习&#xff0c;完成以下一个简单的双栈配置案例&#xff0c;具体结构如下图所示。PC1的 IPv4&#xff1a;192.168.2.1/24 、IPv6&#xff1a;2001:db8:2::2/64&#xff0c;PC2的 IPv4&#xff1a;192.168.3.1/24 、IPv6&#xff1a;2001:db8:3::2/64总共需要两台PC…

Robyn高性能Web框架系列08:使用 Rust 扩展 Robyn

使用 Rust 扩展 RobynPyO3 Bridge示例&#xff1a;一个简单的Rust扩展1、安装必须的组件2、初始化Rust项目3、编写Rust代码4、在Robyn中使用Rust代码在“Robyn高性能Web框架系列07&#xff1a;多进程、性能调优”一节中&#xff0c;我们讲解了Robyn丰富的性能调优方式&#xff…

利用Pandas进行条件替换与向前填充

目录一、需求二、实现代码案例代码详细解释1. 导入库和创建数据2. 条件替换与填充a. 条件掩码 - mask()b. 向前填充 - ffill()c. 类型转换 - astype(int)3. 打印结果三、实际应用场景四、可能的变体五、总结一、需求 示例数据&#xff1a; 项 目 0 1 0 1 0 1 2 0 2 3 …

springboot数据脱敏(接口级别)

文章目录自定义脱敏注解脱敏注解接口脱敏注解反射AOP实现字段脱敏切面定义脱敏策略脱敏策略的接口电话号码脱敏策略邮箱脱敏不脱敏姓名脱敏身份证号脱敏JacksonAOP实现脱敏定义序列化序列化实现脱敏切面定义JacksonThreadLocal拦截器实现脱敏定义ThreadLocal自定义序列化序列化…

Spring核心原理的快速入门:快速了解IoC与DI

IoC IoC&#xff1a;Inversion of Control(控制反转) Spring是一个包含了众多工具的IoC容器(即bean&#xff1a;spring管理的对象),也就是说Spring 是一个“控制反转”的容器。 之前是对象本身管理自己的生命周期等等&#xff0c;现在交给spring来管理对象的生命周期 IoC介绍 …

ffmpeg 中config 文件一些理解

依赖检查 config中看到最多的是&#xff1a; ... nvenc_deps"ffnvcodec" nvenc_deps_any"libdl LoadLibrary" nvenc_encoder_deps"nvenc" ... h264_crystalhd_decoder_select"crystalhd h264_mp4toannexb_bsf h264_parser" h264_cuvid…

Digital Rainwater Collection System (v1.0)

The law doesn’t punish the masses. If only one guy runs his own rainwater system, he gets fined for “illegal mining.” But if millions of households self-host their “digital wells,” the whole centralized model collapses. Cloud providers and regulators …