alioth/before/cha/09=real-time-communication/实时通信方案.md
2025-05-30 09:18:01 +08:00

185 lines
5.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 实时通信方案
- [WebSockets](https://developer.mozilla.org/zh-CN/docs/Web/API/WebSockets_API)
- [Server-sent Event(SSE)](https://developer.mozilla.org/zh-CN/docs/Web/API/Server-sent_events)
- 长链接(服务器端轮询)
- 短链接(客户端轮询)
> [网页端IM通信技术快速入门短轮询、长轮询、SSE、WebSocket (baidu.com)](https://baijiahao.baidu.com/s?id=1700709358061982511&wfr=spider&for=pc)
> [Web端即时通讯技术盘点短轮询、Comet、Websocket、SSE (taodudu.cc)](http://www.taodudu.cc/news/show-614593.html?action=onClick)
> [详解Web端通信方式的演进从Ajax、JSONP 到 SSE、Websocket (360doc.com)](http://www.360doc.com/content/22/0525/15/32573_1033094047.shtml)
## 建设介绍
1. 采用工具
后端ws ^8.13.0
前端socket.io ^4.7.2
2. demo操作
```bash
# 启动server
npm i
npm run start:server
# 启动客户端
cd client
npm i
npm run start:client
# 进入页面输入昵称和ServerIP即可开始聊天
```
## WebSocket
> WebSocket是客户端和服务器之间的可以双向通信的全双工通信协议。
1. 特点
1建立在 TCP 协议之上服务器端的实现比较容易。建立通信时采用http协议
2与 HTTP 协议有着良好的兼容性。默认端口也是80和443并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
3数据格式比较轻量性能开销小通信高效。
4可以发送文本也可以发送二进制数据blob对象或Arraybuffer对象
5收到的数据类型 可以使用binaryType 指定, 显式指定收到的二进制数据类型
6没有同源限制客户端可以与任意服务器通信。
7协议标识符是ws握手http如果加密则为wsstcp +TLS)),服务器网址就是 URL。
2. 使用
```js
const socket = new WebSocket(`ws://hostname:port/path`);
socket.onopen = event => {
// 当socket与服务器练级成功时触发
}
socket.onerror = event =>{
// 当socket出现错误时触发包括网络错误断开连接服务器错误等
console.error('Error',event)
}
socket.onclose = event => {
// 当socket断开连接时触发
// WebSocket没有断线重连机制如需重连在此方法内编写重连逻辑
}
ws.onmessage = event => {
const msg = event.data
// 当接收到服务器发送的消息时触发
ws.send('消息内容');// 这里可以选择二进制数据发送
}
```
## SSE
> SSE的本质其实就是一个HTTP的长连接只不过它给客户端发送的不是一次性的数据包而是一个stream流格式为text/event-stream。所以客户端不会关闭连接会一直等着服务器发过来的新的数据流视频播放就是这样的例子。
1. 特点
1SSE 使用 HTTP 协议现有的服务器软件都支持。WebSocket 是一个独立协议。
2SSE 属于轻量级使用简单WebSocket 协议相对复杂。
3SSE 默认支持断线重连WebSocket 需要自己实现。
4SSE 一般只用来传送文本二进制数据需要编码后传送WebSocket 默认支持传送二进制数据。
5SSE 支持自定义发送的消息类型。
2. 缺点
1客户端无法发送消息需要通过接口单独请求
3. 使用
```js
const eventSource = new EventSource('/api/system/msg/connect?id=' + userId, {
headers: {
'Content-Type': 'text/event-stream',
'Authorization': 'token'
}
});
eventSource.addEventListener("open", function (e) {
console.log('open successfully')
})
/*
* message后端返回信息格式可以和后端协商
*/
eventSource.addEventListener("message", function (e) {
console.log(e.data)
})
/*
* error错误
*/
eventSource.addEventListener("error", function (err) {
// console.log(err)
// 类似的返回信息验证,这里是实例
err && err.status === 401 && console.log('not authorized')
})
```
## 长链接
> 客户端和服务端建立连接后不进行断开,之后客户端再次访问这个服务器上的内容时,继续使用这一条连接通道。
## 短链接
> 客户端和服务端建立连接,发送完数据后立马断开连接。下次要取数据,需要再次建立连接。
>
> Http长连接和TCP长连接的区别在于: TCP 的长连接需要自己去维护一套心跳策略。而Http只需要在请求头加入keep-alive:true即可实现长连接。
## Socket.IO
> Socket.IO 是一个库,可以在客户端和服务器之间实现低延迟, 双向和基于事件的通信。
1. 特点
1它建立在 WebSocket 协议之上并提供额外的保证如果无法建立WebSocket连接连接将回退到HTTP长轮询或自动重新连接。
2自动重新连接
3数据包缓冲。当客户端断开连接时数据包会自动缓冲并在重新连接时发送。
```js
import { io } from "https://cdn.socket.io/4.3.2/socket.io.esm.min.js";
const socket = io("http://127.0.0.1:3000")
socket.on("connect", () => {
//监听连接是否成功
console.log("链接成功");
});
socket.on("disconnect", (reason) => {
//监听连接异常中断
console.log("中断", reason);
});
socket.on("message_event", (data) => {
// "message_event"时后端定义的发送字段
console.log("接收到的消息", data);
})
// 前端主动断开链接
socket.close()
socket.disconnect()
socket.on('connect',() => {
// 与服务器连接成功
console.log('socket链接成功'+socket.id)
})
// 其他事件
// connect连接成功
// connecting正在连接
// disconnect断开连接
// connect_failed连接失败
// error错误发生并且无法被其他事件类型所处理
// reconnect_failed重连失败
// reconnect成功重连
// reconnecting正在重连
```