前端开发 - 即时通信 【socket.io(WebSocket)】 基本使用?

一、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 官方提供的服务端

  1. 仓库地址: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
  2. 克隆到本地之后,使用命令下载对应的包:
    • pnpm install、pnpm add、npm install、yarn add;
  3. 运行项目:pnpm start、npm run start、yarn start;
  4. 测试:
    • 项目跑起之后,有很多地址,我们可以随便选一个进行测试;
    • 在浏览器中打开两个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();
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),如果给的是地址,我们只需关注最后面的单词,这个就是事件名,保险起见,最好还是咨询一下后端😂😂;
  • 注意 :
    • 通信规则很重要;
相关推荐
卸任3 小时前
Vibe coding工具使用心得
前端·ai编程
brien94 小时前
为什么模型标称 1M,Google Antigravity 聊到 256K 却突然失忆?我们给它做了个原生行内监控圆环
前端
修炼的dance4 小时前
录屏关键帧间隔多少合适?六档实测,2秒到10秒小了75.6%
前端
Lank_M4 小时前
关键帧从1秒拉到10秒,录屏小87.3%,摄像头小10.8%
前端
补码缩写4 小时前
用 ffprobe 拆录屏,八成字节在 29 个关键帧上
前端
百思不得小李4 小时前
一个复杂的动态表单是如何实现的
前端·设计模式
陈随易4 小时前
Cmder 停更 17 个月,2.0 支持 Windows Terminal
前端·后端·程序员
风骏时光牛马5 小时前
前沿视界
前端
kyriewen5 小时前
我扫了 814 个依赖,97 个还敢要 Node 10
前端·javascript·程序员
陈随易5 小时前
3000 万人在用的翻译插件,重写一遍就是一门生意
前端·后端·程序员