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 否则会形成Buffer
console.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