chat

主要实现方式

在实现即时通讯(IM)系统的前后端交互时,长轮询(Long Polling)、定时轮询(Polling)、SSE(Server-Sent Events)和 WebSocket(WS) 是常见的通信模式,但它们各有适用场景和优缺点。

以下是对比分析及现代 IM 系统的典型技术选型:


1. 通信模式对比

| 技术 | 协议 | 方向性 | 实时性 | 适用场景 | 缺点 | |——————–|———–|————–|————–|———————————-|———————————–| | 定时轮询 | HTTP | 客户端主动拉取 | 低(延迟高) | 简单场景,兼容性要求高 | 资源浪费(频繁请求)、延迟不可控 | | 长轮询 | HTTP | 客户端半主动 | 中(依赖超时) | 兼容老旧设备,短时实时需求 | 连接频繁重建,服务器并发压力大 | | SSE | HTTP | 服务端单向推送 | 高(单向流) | 服务端主动通知(如新闻推送) | 仅支持单向通信,需浏览器兼容性 | | WebSocket | WS/WSS | 全双工双向通信 | 高(实时) | 即时聊天、实时协作、游戏 | 需协议升级,部分网络设备可能拦截 |

详细介绍一下 websocket

WebSocket 是一种网络通信协议,它提供了在客户端和服务器之间建立持久化的双向通信通道,使得客户端和服务器能够进行实时的数据交换。

与传统的 HTTP 请求/响应模型不同,WebSocket 允许服务器主动向客户端推送数据,不需要客户端轮询服务器。

WebSocket 的工作原理

  1. 建立连接
    • WebSocket 连接通过 HTTP 协议发起,并使用 HTTP 的 Upgrade 头部将协议从 HTTP 升级到 WebSocket。
    • 客户端发送 WebSocket 请求:客户端发送 HTTP 请求(通过 Sec-WebSocket-Key 头标识请求)。
    • 服务器响应确认:如果服务器支持 WebSocket,它会在响应中返回 Sec-WebSocket-Accept 头部,表示协议切换成功。
  2. 数据传输
    • 一旦连接建立,客户端和服务器之间就可以通过 WebSocket 协议进行双向通信。数据可以以文本或二进制格式发送。
    • WebSocket 使用 (Frame)来封装数据,保证了数据的完整性和高效性。
    • 数据传输是全双工的,客户端和服务器可以同时发送和接收消息。
  3. 关闭连接
    • 一方可以主动关闭连接,发送一个关闭帧,另一方响应关闭帧,最终关闭连接。
    • WebSocket 连接的关闭是通过发送和接收特定的帧来实现的。

WebSocket 的特点

  1. 持久化连接
    • 一旦建立连接,连接可以持续不断,直到某一方关闭连接。客户端和服务器之间不需要频繁地重新建立连接。
  2. 双向通信
    • WebSocket 是全双工的,允许服务器主动向客户端发送数据,这使得它非常适合实时应用(如即时通讯、游戏、股票行情等)。
  3. 低延迟
    • 由于 WebSocket 连接是持久化的,数据传输不需要通过传统的 HTTP 请求/响应模型,因此相比轮询或长轮询,WebSocket 可以显著减少延迟。
  4. 高效
    • WebSocket 消息头非常小,相比 HTTP 请求的完整头部,WebSocket 的开销更小,因此传输效率更高。
  5. 跨域支持
    • WebSocket 不受跨域请求的限制,因此可以在不同域之间建立连接,适合分布式系统的通信需求。

WebSocket 与其他通信方式的对比

特性 WebSocket HTTP 请求/响应 长轮询
连接方式 双向持久化连接 单向请求响应 双向,但每次请求后断开
通信模式 全双工 半双工 半双工
延迟 较高
适用场景 实时消息,游戏,股票行情等 普通的请求响应 实时消息,实时通知等
效率 较低

WebSocket 示例代码

1. 后端(Spring Boot)WebSocket 实现

Spring Boot 提供了对 WebSocket 的支持,可以通过 spring-websocket 来集成 WebSocket。

pom.xml 添加依赖:

  [xml]
1
2
3
4
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>

配置 WebSocket 端点

  [java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.config.annotation.EnableWebSocket; import org.springframework.web.socket.config.annotation.WebSocketConfigurer; import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor; @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(new MyWebSocketHandler(), "/chat") .addInterceptors(new HttpSessionHandshakeInterceptor()) .setAllowedOrigins("*"); } }

WebSocket 处理器

  [java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.handler.TextWebSocketHandler; public class MyWebSocketHandler extends TextWebSocketHandler { @Override public void handleTextMessage(WebSocketSession session, TextMessage message) { try { // Echo message back to client session.sendMessage(new TextMessage("Server: " + message.getPayload())); } catch (Exception e) { e.printStackTrace(); } } }

2. 前端(Vue.js)WebSocket 实现

前端可以通过浏览器的 WebSocket API 来建立 WebSocket 连接。

  [javascript]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<template> <div> <h3>WebSocket Chat</h3> <input v-model="message" @keyup.enter="sendMessage" placeholder="Type a message" /> <ul> <li v-for="msg in messages" :key="msg"></li> </ul> </div> </template> <script> export default { data() { return { message: '', messages: [], socket: null, }; }, mounted() { this.socket = new WebSocket('ws://localhost:8080/chat'); this.socket.onopen = () => { console.log('WebSocket connection opened'); }; this.socket.onmessage = (event) => { this.messages.push(event.data); }; this.socket.onclose = () => { console.log('WebSocket connection closed'); }; }, methods: { sendMessage() { if (this.message) { this.socket.send(this.message); this.message = ''; // Clear input } }, }, }; </script> <style scoped> input { margin-bottom: 10px; } </style>

WebSocket 安全性

  1. WebSocket over TLS (wss://)
    • WebSocket 支持加密传输(wss://),和 HTTPS 类似,它为 WebSocket 通信提供了加密保护。
  2. 身份验证和授权
    • WebSocket 本身没有内建身份验证机制,通常需要在握手阶段通过 HTTP 头进行身份验证,或者通过 WebSocket 消息来进行认证。
  3. 防止 DoS 攻击
    • WebSocket 可以被滥用进行服务拒绝攻击(DoS),因此应对每个连接进行限制和监控。

总结

WebSocket 是一种非常适合实时通讯的协议,特别适用于即时聊天、在线游戏、实时股票行情等应用场景。

与传统的轮询或长轮询方式相比,WebSocket 提供了更高效、低延迟的通信方式,支持双向通信,并且可以在连接建立后持续进行数据交换。

如果你正在构建需要高效实时通讯的应用,WebSocket 是一个很好的选择。

后端是 java springboot 技术栈,前段主要是 js vue 技术栈。给出 websocket 前后端代码实现

总结

参考资料