一、前言
思考要做一个聊天室,该如何去做。
现有一个聊天室,其中有张三、李四、王五这三人在里面。
张三发送一条消息,李四和王五要接收到这条消息。如何接收?
张三是直接发送给李四和王五的么?不是,而是发送消息给服务器
早期的实现方式:
客户端A将消息发送给服务器 (setMessage)。客户端B去找服务器要消息 (getMessage) 客户端B不知道该什么时候去向服务器要消息,所以会做一个定时器每隔一段时间就去找服务器要消息 这种实现方式叫做 轮询。
轮询方式存在的问题:
- 服务器压力山大
- 实时性不高
长连接的 socket 实现方式:
socket 是实现客户端与服务端双向通信的一种技术。
双向通信:客户端与服务端在第一次建立起连接之后,不会主动去断掉。并且 除了可以客服端主动向服务器发消息之外,服务端也可以主动去给客服端发消息
客户端A \ B \ C 都与服务器建立了 socket 连接 客户端A向服务器发送一条消息。服务器收到消息之后可以立马给客户端B与客服端C去发消息。
socket 除了用于聊天室还能在那些场景适用
- 股票交易
- 聊天室
- 实时图表更新
- …
二、ws 模块实现
1. 后端实现
- 安装 ws
$ npm install ws
- 示例代码
// 引入 ws 模块const WebSocket = require('ws')// 创建 WebSocket 服务const wss = new WebSocket.Server({port: 3000, // 设置服务监听的端口号})// 监听连接建立wss.on('connection', (socket) => {// socket 连接实例// 监听客户端发来的消息socket.on('message', (message) => {})// 给客户端发送消息socket.send('消息内容')})
2. 前端实现
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title></head><body><script>// 建立连接const socket = new WebSocket('ws://localhost:8080')// 连接成功socket.onopen = function () {console.log('连接成功')}// 监听服务端发来的消息socket.onmessage = function (event) {console.log(event.data)}// 给服务端发送消息socket.send('hello')</script></body></html>
三、socket.io 实现
1. 后端实现
- 安装 socket.io
$ npm install socket.io
- 代码示例
// 引入 expressconst express = require("express");// 引入 socketIoconst socketIo = require("socket.io");// 生成 express 实例const app = express();// 生成 服务const server = app.listen(3000);// socket.io 监听服务const io = socketIo.listen(server);// socket 连接io.on("connection", socket => {// 监听客户端发来的消息socket.on("message", data => {console.log(data);});// 给自己会消息socket.emit("message", {message: "hello"});// 给其它用户广播socket.broadcast.emit("message", {message: "hello"});});
2. 前端实现
需要安装客户端连接浏览器的插件:
npm i scoket.io-client
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title></head><body><script src="./socket.io.js"></script><script>// 建立连接const socket = io('http://localhost:3000')// 连接成功socket.on('connect', () => {console.log('连接成功')})// 监听服务端发来的消息socket.on('message', (data) => {console.log(data)})// 给服务端发送消息socket.emit('message', '我的天')</script></body></html>
