大家好,我是前端西瓜哥,今天我们用 WebSocket 来实现一个简单的聊天室。

WebSocket 是一个应用层协议,有点类似 HTTP。但和 HTTP 不一样的是,它支持真正的全双工,即不仅客户端可以主动发消息给服务端,服务端也可以主动发消息给客户端。

尤其是后者,让我们不用再基于 HTTP 长轮询或短轮询的低效方式来实现服务端通知。相比 HTTP,WebSocket 的服务端推送更轻量,并能减少服务端的压力。

服务端

nodejs 并没有提供原生的 websocket 模块。如果要实现,需要基于 net 模块,根据 websocket 标准去做实现。

因为实现很复杂,所以西瓜哥我选择直接用第三库 ws。

yarn add ws

类似 nodejs 原生的 http 等模块,ws 库支持 WebSocket 的服务端或客户端, 提供偏底层的 API。

我们显示服务端代码:

import { WebSocketServer } from "ws";// 创建一个 ws 服务
const wsSever = new WebSocketServer({port: 6060,
});// 每当一个客户端进行了 ws 连接,就会创建一个 ws 对象
wsSever.on("connection", (ws) => {// 新客户端连接时,广播wsSever.clients.forEach((client) => {client.send(`有人进入聊天室,当前聊天室人数:${wsSever.clients.size}`);});// 广播任何客户端发送的消息ws.on("message", (data) => {const msg = data.toString();wsSever.clients.forEach((client) => {client.send(msg);});});// 当有客户端退出时,广播ws.on("close", () => {wsSever.clients.forEach((client) => {client.send(`有人退出了聊天室,当前聊天室人数:${wsSever.clients.size}`);});});
});

每当一个客户端进行了 websocket 连接,都会触发 wsServer 的 connection 事件,然后拿到一个 ws 对象。

这个 ws 对象代表了某个客户端和服务端的连接,我们可以通过它来接收对应客户端的消息,和服务端对指定客户端进行主动消息推送。

新创建的 ws 对象会在建立连接时保存到 wsServer.clients 集合下,并在关闭连接后移除。所以我们可以利用这个 wsServer.clients 来进行广播,实现聊天室功能。

客户端

客户端使用原生的 WebSocket 对象,来和服务端进行 websocket 连接。

const ws = new WebSocket('ws://localhost:6060');ws.addEventListener('message', (event) => {const div = document.createElement('div');div.innerText = event.data;document.body.append(div);
})// 点击发送按钮,将输入框中的内容发送给服务器
const input = document.querySelector('input');
const btn = document.querySelector('button');
btn.onclick = () => {ws.send(input.value);input.value = '';
}

效果

改为使用 Socket.IO

ws 库是偏底层的实现,比较简单。

另一个库 Socket.IO 的底层使用了 ws,并做功能上的增强,提供更多的能力。

相比 ws,Socket.IO 能够做到:

  1. 如果浏览器不支持 WebSocket,回退为 HTTP 长轮询方案来模拟 WebSocket( WebSocket 于 2011 年完成 RFC,已经很久了,目前来说主流浏览器都已经支持 WebSocket 了,还不支持 WebSocket 的浏览器是屑);
  2. 使用心跳包机制实现了自动重连。
  3. 包缓存。断连时发送数据,会将数据保存下来,等重新连接后再发送;
  4. 自定义事件支持;
  5. 广播;

相比自己去一个个实现,使用流行的轮子可能是更好的选择。

我们将前面的功能用 Socket.IO 实现一下。

服务端:

import { Server } from "socket.io";// socket.io v3.x 开始默认不允许跨域,需要在配置显式设置为允许跨域
const io = new Server(6060, { cors: { origin: "*" } });io.on("connection", (socket) => {// 新客户端连接时,广播io.emit("chat", `有人进入聊天室,当前聊天室人数:${io.engine.clientsCount}`);// 广播任何客户端发送的消息socket.on("chat", (data) => {io.emit("chat", data);});// 当有客户端退出时,广播socket.on("disconnect", () => {io.emit("chat", `有人退出了聊天室,当前聊天室人数:${io.engine.clientsCount}`);});
});

需要特别注意的是,Socket.IO 的 v3.x 版本开始,默认不允许跨域,需要在配置显式设置为允许跨域。

客户端:

const socket = io('ws://localhost:6060');socket.on('chat', (data) => {const div = document.createElement('div');div.innerText = data;document.body.append(div);
})// 点击发送按钮,将输入框中的内容发送给服务器
const input = document.querySelector('input');
const btn = document.querySelector('button');
btn.onclick = () => {console.log('发送');socket.emit('chat', input.value);input.value = '';
}

Socket.IO 优点是实现了生产环境需要的底层非业务能力,让我们能更心无旁骛地去编写业务代码。

缺点是丢失了灵活性。因为做了定制化,所以需要配套使用 Socket.IO 的客户端和服务端库的包,某种意义脱离了网络协议标准。在出现跨语言(比如前端是 JS,后端是 Java)的场景时,需要提供对应的语言的 Socket.IO 实现。

demo

demo 已经放到 github 上了,使用方法在 README.md 中有说明。

https://github.com/F-star/websocket-chat-demo

结尾

本文演示了 WebSocket 简易的聊天室功能是如何实现的,希望对你有所帮助。

我是前端西瓜哥,欢迎关注我,学习更多前端知识。

WebSocket 入门:简易聊天室相关推荐

  1. 基于Node.js + WebSocket 的简易聊天室

    代码地址如下: http://www.demodashi.com/demo/13282.html Node.js聊天室运行说明 Node.js的本质就是运行在服务端的JavaScript.Node.j ...

  2. 原创 回归前端学习第21天-实现俄罗斯方块小游戏3(深入了解Websocket~优化简易聊天室)

    对昨天的简易聊天室进行优化 增加一个mes对象,将传送的数据放在对象里 增加一个mes对象,将传送的数据放在对象里 wsServer.js中替换代码 broadcast(conn.nickname + ...

  3. nodejs websocket 实现简易聊天室功能

    文章目录 1. 服务端 app.js 代码 2. 客户端 app.html 代码 3. 样式代码 app.css 4. nodemon 辅助开发 首先说明,以下代码都是基于 Nodejs+webSoc ...

  4. Vue3 -- 基于Websocket实现简易聊天室

    文章目录 标题 代码地址 表情包资源 chat.data.ts index.vue 标题 接上一篇博文 这里使用 Vue3 + Typescript + Websocket 实现在线聊天功能的前端部分 ...

  5. webSocket——Vue2简易聊天室

    WebSocket原生实现 WebSocket-Vue2 WebSocket-Vue3 Vue2版本实现 前端实现 目录结构 login.vue 登录 <template><div& ...

  6. websocket实现简易聊天室

    websocket支持全双工通信,也就是客户端和服务端双向通信.以前都是通过http轮询的方式实现实时的,这非常耗性能.Websocket不仅能节省资源和带宽,还能实现长链接的作用 前端通过创建Web ...

  7. WebSocket——vue3简易聊天室

    WebSocket原生实现 WebSocket-Vue2 WebSocket-Vue3 前端实现 目录结构 登录(LoginView.vue) <template><div clas ...

  8. Java WebSocket实现简易聊天室

    一.Socket简介 Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求.Socket的英文原义是"孔"或 ...

  9. 前端websocket实现简易聊天室

    分为客户端和服务端,客户端就是一个简单的html页面,服务端使用node进行编写.具体代码如下 index.html <!DOCTYPE html> <html> <he ...

  10. SpringBoot整合WebSocket实现简易聊天室

    文章目录 什么是WebSocket ? WebSocket通信模型 为什么需要WebSocket Websocket与http的关系 SpringBoot集成WebSocket 什么是WebSocke ...

最新文章

  1. 如何快速坐地铁高铁?舒工为您带来满满的都是干货~
  2. Sqlite3的安装Windows
  3. Conda创建环境失败:CondaHTTPError: HTTP 000 CONNECTION FAILED
  4. EonerCMS——做一个仿桌面系统的CMS(三)
  5. 深入解析阿里 PouchContainer 如何实现容器原地升级
  6. T-SQL :SQL Server 定义数据完整性 5大约束
  7. VirtualBox Ubuntu个人配置
  8. Hotel POJ - 3667(线段树 + 区间合并
  9. java 内存分配实例_java学习(四) —— 内存分配浅析
  10. .NET中的Assembly分析
  11. 前端—每天5道面试题(6)
  12. 屏幕共享软件开发_工作生活离不开软件,你知道什么是免费软件与共享软件吗?...
  13. SparkStreaming kafka zookeeper本地环境调试安装
  14. CSDB Blog快速备份程序-备份你自己的Blog
  15. L2-004 这是二叉搜索树吗? (25分)*
  16. C语言中文分号,问什么C程序里总是提示缺少分号;,而明明有分号?
  17. css实现两列容器等高布局,CSS等高布局的实现方法
  18. 连接linux服务器安卓模拟器,云服务器怎么运行安卓模拟器
  19. 要取好名字的来这儿!哈哈
  20. Centos7安装Geany

热门文章

  1. 英国帝国理工出品——SSIM对抗攻击
  2. Windows系统win10系统流程图软件推荐
  3. 上海车展:比亚迪宋L概念车全球首发,这是要硬扛特斯拉?
  4. 【产品】项目管理的五大阶段
  5. ISCC2021 Web WP
  6. 二叉树 最小公共祖先 c++版
  7. linux tuxedo查看服务进程数,tuxedo管理命令之tmboot与tmshutdown
  8. 测试POST传输工具【poster】。
  9. Powershell / windows终端 无法加载文件 因为在此系统上禁止运行脚本。有关详细信息,请参阅 https:/go.microsoft.com/fwlink/?LinkID=135170
  10. 万丈高楼平地起,基础很重要