前端开发 - 即时通信 【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),如果给的是地址,我们只需关注最后面的单词,这个就是事件名,保险起见,最好还是咨询一下后端😂😂;
  • 注意 :
    • 通信规则很重要;
相关推荐
java1234_小锋5 小时前
【技术专题】HTML5 网页技术 - HTML5 Canvas 基础以及动画入门
前端·html·html5
知了学历孙老师8 小时前
小自考的校考和统考,出题方和难度差在哪
java·大数据·前端
ShineWinsu10 小时前
对于JavaScript:操作元素的解析
开发语言·前端·javascript·面试·web·dom·元素
福兮说11 小时前
JSON 格式正确,数据就可靠吗?我用一份自编配置检查类型与空值
java·前端·json
程序员老赵13 小时前
Docker 部署青龙面板:轻松搭建定时任务管理平台
前端·docker·开源
Swot13 小时前
Asciidoctor 公式数字下标错位问题:原因分析与解决方案
前端
Swot13 小时前
leo-editor 中将 Markdown 内容转成 asciidoc 格式
前端
狒狒AI13 小时前
Remotion / GSAP+Three / HyperFrames / Skia 四栈实测:代码渲染知识视频的选栈方法(附开源技能)
前端·人工智能·aigc
修炼的dance13 小时前
浏览器里导出H.265,8.5秒和55.5秒差在硬件
前端
补码缩写13 小时前
WebCodecs选编码器,探测之后还要验解码和播放
前端