websoket是干么的
websoket简单来说就是允许服务端主动向客户端推送数据的一种技术。他可以使客户端和服务端之间交换数据变得简单,浏览器和服务器只需要完成一次握手(握手指的是:创建websoket需要向浏览器发送请求,之后服务器进行回应,这个过程称为握手),两者之间就可以创建持久的连接,进行双向数据传输。
websoket是一种在单个TCP连接上进行的全双工通信的协议。由于协议是全双工的,所以服务器可以随时主动给客户端下发数据。相对于HTTP请求需要等待客户端发起请求服务端才能响应,延迟明显更少;
保持连接状态。与HTTP不同的是,Websocket需要先创建连接,这就使得其成为一种有状态的协议,之后通信时可以省略部分状态信息。而HTTP请求可能需要在每个请求都携带状态信息(如身份认证等
很多网站为了实现推送技术,一般用的技术都是轮询(轮询简单来说:使用定时器每隔一段时间向后端发送一次请求俗称:程控输出入)由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。
基于websoket实现一个简单的消息通信
使用到的技术有vite node ws
先初始化两个项目一个web端的,一个服务端
npm init -y
npm i vite -D
更改启动命令
{"name": "web","version": "1.0.0","description": "","main": "index.js","scripts": {"dev": "vite"},"keywords": [],"author": "","license": "ISC","devDependencies": {"vite": "^4.0.4"}
}
创建 index.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><h1>欢迎来到聊天室</h1><ul id="ul"></ul><input id="input" type="text"><button id="btn">点击发送</button>
</body>
<script>// 1 安装vite npm i vite -D/** 前端* open 建立连接* close 关闭连接* error 错误信息* message 接受后端返回的信息* */; ((Window, WebSocket, Storage) => {console.log(localStorage.getItem('name'))let ws = new WebSocket('ws:localhost:8000')function bindTab() {btn.addEventListener('click', btnHandle)ws.addEventListener('message', messageHandle)ws.addEventListener('close', closeHandle)ws.addEventListener('error', errorHandle)ws.addEventListener('open', openHandle)}const closeHandle = () => {console.log('close');}const errorHandle = () => {console.log('error');}const openHandle = () => {console.log('open');}const messageHandle = (res) => {ul.appendChild(render(res.data))}const btnHandle = () => {console.log(input.value)if (!Storage.getItem('name')) {console.log(Storage.getItem('name'))window.location.href = 'http://127.0.0.1:5173/login.html'}let obj = JSON.stringify({text: input.value,time: new Date().toLocaleString(),name: localStorage.getItem('name')})console.log(2, ws)// 向后端发送数据将参数转换为字符串传入。ws.send(obj)}const render = (value) => {let msg = JSON.parse(value)let li = document.createElement('li')li.innerHTML = `<li>内容:${msg.text}--姓名:${msg.name}--时间:${msg.time}</li>`return li}bindTab()})(Window, WebSocket, localStorage)</script></html>
创建login.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><h1>欢迎来到聊天室</h1><p>请输入你的名字:<input id="input" type="text"> <button id="btn">注册</button></p></body>
<script>btn.addEventListener('click', function () {localStorage.setItem('name', JSON.stringify(input.value))window.location.href = 'http://127.0.0.1:5173/'})</script></html>
node服务端
npm init -y
npm i ws -D
没有nodemon 安装 npm i nodemon
{"name": "node","version": "1.0.0","description": "","main": "index.js","scripts": {"dev": "nodemon index.js"},"keywords": [],"author": "","license": "ISC","dependencies": {"nodemon": "^2.0.20","ws": "^8.12.0"}
}
创建index.js
const Ws = require('ws')
// 监听在8000端口
const wss = new Ws.Server({port: 8000,
})/** 后端* open 建立连接* close 关闭连接* error 错误信息* message 接受后端返回的信息* connection 后端表示已经连接上了* */// ws 插件 nodejs-websocket 插件
wss.on('open', () => {console.log('open')
})
wss.on('connection', function (ws) {console.log('连接成功', ws)ws.on('message', getMessage)
})wss.on('message', (res) => {console.log('message', res);
})
wss.on('error', () => {console.log('error' );})
wss.on('close', () => {console.log('close' );
})function getMessage(msg) {//<Buffer 7b 22 69 64 22 3a 31 2c 22 6e 61 6d 65 22 3a 22 e5 bc a0 e4 b8 89 22// 必须将msg进行toString 否则会形成Bufferconsole.log('ws', msg.toString())// toJSON不是转成原数据json,而是把json buffer数据转化成json格式。console.log(msg.toJSON());// clients 向客户端推送数据wss.clients.forEach(c => {c.send(msg.toString())})
}
启动命令都是 npm run dev