一、WebSocket 简介
- 什么是
websocket
?- 是一种 网络通信协议 ,和
http
协议一样;
- 是一种 网络通信协议 ,和
- 为什么需要
websocket
协议?http
协议通信 只能由 客户端发起 ,不能双向通信 ;- 简单来说,
http
是客户端发一个,服务端响应一个; - 如果你不发请求,服务端是不会有响应的;
- 简单来说,
- 而
websocket
,只要客户端向服务端发起邀请,建立连接,服务端应答之后,就可以发送消息了(不管是客户端还是服务端还是两个同时都能发),关闭连接之后,通信就结束了;
- 项目中使用
socket.io-client
来实现 客户端功能 ,它是基于websocket
的JS
库;
二、JS 内置的 WebSocket 基本使用
WebSocket
是JS
内置的构造函数;- 使用原生
WebSocket
进行前后端通信的时候,该构造函数需要一个参数:
- 服务端的通信地址;
2.1 建立连接
js
const ws = new WebSocket('wss://javascript.info/article/websocket/demo/hello');
2.2 监听连接成功 - ws.onopen
- 服务器应答之后就连接成功了
- 应答之后会触发
onopen()
处理函数;
js
ws.onopen = () => {
console.log('连接成功');
}
2.3 如何发消息 - ws.send()
html
<body>
<button id="btn">发消息</button>
<script>
document.querySelector('#btn').onclick = () => {
ws.send('你好服务器!');
};
</script>
</body>
- 如何检测发向服务端的消息发送成功了?
- 只要能接收到服务器发送来的消息,就说明发送成功了
2.4 如何接消息 - ws.onmessage
onmessage()
➡ 该函数有一个实参$e / event
,**$e.data
**就是服务端向客户端发送的消息;
js
ws.onmessage = ($e) => {
console.log('服务端向客户端发送的消息', $e);
};
2.5 如何关闭连接
- 关闭服务器连接有两种方式可以关闭,一种是客户端关闭(推荐),还有一种是服务端主动关闭(不推荐);
- 在我们开发的过程中,一定是要我们 客户端去关闭的;
2.5.1 客户端关闭 - ws.close()
html
<body>
<button id="btn2">关闭连接</button>
<script>
document.querySelector('#btn2').onclick = () => {
ws.close();
};
</script>
</body>
2.5.2 服务端主动关闭
- 当服务器向客户端发送消息等几秒之后,此次的连接会自动关闭,但是 是 服务端主动关闭;
2.6 监听通信关闭 - ws.close
js
ws.onclose = () => {
console.log('连接关闭');
};
- ❗ 注意 :
- 第一次:
- 服务端关闭连接;
- 服务端给客户端发送消息等一会之后,自动关闭了连接;
- 第二次:
- 客户端关闭连接;
- 我手动点击的关闭连接;
三、体验 Socket.IO
3.1 Socket.IO
是什么?
- 基于
WebSocket
的 即时通讯 的解决方案,提供后端即时通信服务,前端连接后端JS库; - socket.io 是一个基于 WebSocket 的 CS(客户端-服务端)的实时通信库;
- 使用它可以在后端提供一个即时通讯服务;
- 它也提供一个 js 库,在前端可以去链接后端的 socket.io 创建的服务;
- 总结 :它是一套基于 websocket 前后端 即时通讯 解决方案;
3.2 克隆 socket.io
官方提供的服务端
- 仓库地址:
git clone https://github.com/socketio/chat-example.git
; 注意:- 可能克隆的项目跑不起来,提示
Error: ENOENT: no such file or directory, stat xxx
(如果哪位大佬解决了这个问题,告诉小弟一声哈😁); - 大家可以克隆这个比较旧的项目体验:
git clone https://gitee.com/draw-a-beautiful-yarn/socket-io.git
- 可能克隆的项目跑不起来,提示
- 克隆到本地之后,使用命令下载对应的包:
pnpm install、pnpm add、npm install、yarn add
;
- 运行项目:
pnpm start、npm run start、yarn start
; - 测试:
- 项目跑起之后,有很多地址,我们可以随便选一个进行测试;
- 在浏览器中打开两个
Tab
页,输入选择的地址,进行发送消息,可以看到,A窗口发送的消息在B窗口中也能看到,反之同理;
注意:
- 可能在运行项目的时候会报错:
- 报错信息:
- 报错原因为是因为没有
express
这个包;- 解决方案 :
- 安装
express
包:
pnpm install express@4
;- 大家可以自行选择命令(
pnpm
快很多😂😂);
四、socket.io-client 在项目中的使用
4.1 安装 socket.io-client
js
// 选择一个命令下载即可
pnpm add socket.io-client
npm install socket.io-client
yarn add socket.io-client
4.2 初始化socket 及 常用事件
ts
import io from 'socket.io';
// 初始化 socket.io
const socket = io('服务器地址');
// 连接成功触发的事件
socket.on('content', () => {
console.log('连接成功');
});
// 客户端 发消息
socket.emit('前后端约定的事件名称', '要发送的消息');
// 客户端接收服务端发送的消息
socket.on('前后端约定的事件名称', (msg) => {
// msg 就是后端发送的消息
console.log(msg);
});
// 关闭连接
socket.close();
// 关闭连接触发的函数(触发这个函数的时候,说明服务已经断开了)
socket.on('disconnect', () => {
console.log('关闭连接');
});
4.3 ❗❗ 在项目中的使用
4.3.1 初始化 socket
- 初始化的时机:
- 在 组件初始化完毕之后 开始初始化socket;
Vue2
:created() / mounted()
;Vue3
:onMounted()
;
- 在 组件初始化完毕之后 开始初始化socket;
js
// Vue2
created() {
// 参数1:不传默认是当前服务域名,开发中传入服务器地址
// 参数2:配置参数,根据需求(一般 token 是必须传递的)
const socket = io(参数1, 参数2);
// 将以上需要的地址、配置参数完成之后,就可以建立连接
}
// Vue3
import { onMounted } from 'vue';
onMounted(() => {
// 参数1:不传默认是当前服务域名,开发中传入服务器地址
// 参数2:配置参数,根据需求(一般 token 是必须传递的)
const socket = io(参数1, 参数2);
// 将以上需要的地址、配置参数完成之后,就可以建立连接
});
4.3.2 添加基本事件
- 我这里就以
Vue3 + TypeScript
为例开始写(如果是Vue2
的项目,不用写类型注解,更换钩子函数即可);
ts
// Vue2: import io from 'socket.io';
// Vue3
import { io, type Socket } from 'socket.io';
import { onMounted, onUnmounted } from 'vue';
// 将 socket 定义在这里是因为,在组件加载完毕 和 卸载(或这说离开当前页面)的时候,都需要使用到socket;
let socket: Socket;
// 在组件初始化的时候建立连接
// Vue2: mounted()
onMounted(() => {
// 初始化 socket
socket = io('服务器地址', options);
// 建立连接
socket.on('connect', () => {
console.log('建立连接');
});
// 客户端发送消息失败触发的函数
// 消息发送失败的时候,可以在这个事件处理函数中进行相应逻辑的处理
socket.on('error', () => {
console.log('客户端发送消息失败');
});
// 关闭连接
socket.on('disconnect', () => {
console.log('关闭连接');
});
});
// 组件卸载钩子函数
// Vue2: destroyed()
onUnmounted(() => {
// 组件卸载 / 离开当前页面 的时候 关闭连接
socket.close();
});
4.3.3 通信规则(聊天事件)
- 我们和服务器聊天的时候,需要定义对应的事件来触发不同的聊天机制;
- 关于定义的事件,需要和后端商议,等后端那边完成之后,有时候会直接给我们一个事件名称,有时候给的是一个接口地址(
eg:https://xxx.xxx/getMessage
),如果给的是地址,我们只需关注最后面的单词,这个就是事件名,保险起见,最好还是咨询一下后端😂😂; - 注意 :
- 通信规则很重要;