什么是websocket
WebSocket是一种网络传输协议,可在单个TCP连接上进行全双工通信,位于OSI模型的应用层,是H5新增的 API。
- TCP连接,与HTTP协议兼容(一个项目里面即可有http协议,又可以有ws)
- 双向通信,主动推送(服务端向客户端)
- 无同源限制,协议标识符是ws(加密wss,没有跨域的限制)
websocket应用场景
- 聊天、消息、点赞
- 直播评论(弹幕)
- 游戏、协同编辑、基于未知的应用
基本使用 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>
<style>
#messagebox {
width: 300px;
height: 300px;
border: 1px solid #000;
}
</style>
</head>
<body>
<div>
<input type="text" placeholder="请输入您的消息" />
<button>发送消息</button>
<div id="messagebox"></div>
</div>
<script>
var input = document.querySelector('input');
var button = document.querySelector('button');
var msgBox = document.querySelector('#messagebox');
console.log(input);
console.log(button);
console.log(msgBox);
const ws = new WebSocket("ws://localhost:8080");
button.addEventListener('click', function () {
console.log('click')
})
// ws事件监听
ws.addEventListener('open', function () {
console.log('连接成功了')
})
ws.addEventListener('message', function (e) {
console.log(e)
})
ws.addEventListener('close', function () {
console.log('连接关闭')
})
ws.addEventListener('error', function () {
console.log('连接异常')
})
</script>
</body>
</html>
基本使用 node部分
yarn add nodejs-websocket
const ws = require('nodejs-websocket');
const server = ws.createServer((conn) => {
console.log('有人连接上来了')
conn.on('error', () => {
console.log('连接异常!!!')
})
})
server.listen(8080, () => {
console.log('websocket服务启动成功了,监听了端口8080');
})
发送消息并且展示到页面上
<!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>
<style>
#messagebox {
width: 300px;
height: 300px;
border: 1px solid #000;
}
</style>
</head>
<body>
<div>
<input type="text" placeholder="请输入您的消息" />
<button>发送消息</button>
<div id="messagebox"></div>
</div>
<script>
var input = document.querySelector('input');
var button = document.querySelector('button');
var msgBox = document.querySelector('#messagebox');
console.log(input);
console.log(button);
console.log(msgBox);
const ws = new WebSocket("ws://localhost:8080");
button.addEventListener('click', function () {
// console.log(input.value)
let value = input.value
ws.send(value)
})
// ws事件监听
ws.addEventListener('open', function () {
console.log('连接成功了')
})
ws.addEventListener('message', function (e) {
console.log(e,'message')
let data = e.data;
let div = document.createElement('div')
div.innerHTML = `${data}`;
msgBox.appendChild(div)
input.value = ''
})
ws.addEventListener('close', function () {
console.log('连接关闭')
})
ws.addEventListener('error', function () {
console.log('连接异常')
})
</script>
</body>
</html>
const ws = require('nodejs-websocket');
const server = ws.createServer(connect => {
console.log('有用户连接上来了');
connect.on('text', data => {
console.log('接收到了用户的数据', data);
// 2.2 给用户一个响应的数据
connect.send(data);
})
// 2.3 用户关闭链接,只要websocket链接断开了就会触发这个事件
connect.on("close", function (code, reason) {
console.log("用户关闭链接")
})
// 注册一个error,处理用户的报错信息
connect.on('error', () => {
console.log('用户连接异常')
})
})
server.listen(8080, () => {
console.log('websocket服务启动成功了,监听了端口8080');
})
添加广播事件
让所有人接收到消息
const ws = require('nodejs-websocket');
const server = ws.createServer(connect => {
console.log('有用户连接上来了');
connect.on('text', data => {
console.log('接收到了用户的数据', data);
// 2.2 给用户一个响应的数据
// connect.send(data);
broadcast(data);
})
// 2.3 用户关闭链接,只要websocket链接断开了就会触发这个事件
connect.on("close", function (code, reason) {
console.log("用户关闭链接")
})
// 注册一个error,处理用户的报错信息
connect.on('error', () => {
console.log('用户连接异常')
})
})
// 广播消息
function broadcast(data) {
server.connections.forEach(item => {
item.send(data)
})
}
server.listen(8080, () => {
console.log('websocket服务启动成功了,监听了端口8080');
})
简单聊天室
<!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>
<style>
#messagebox {
width: 300px;
height: 300px;
border: 1px solid #000;
}
</style>
</head>
<body>
<div>
<input type="text" placeholder="请输入您的消息" />
<button>发送消息</button>
<div id="messagebox"></div>
</div>
<script>
var input = document.querySelector('input');
var button = document.querySelector('button');
var msgBox = document.querySelector('#messagebox');
console.log(input);
console.log(button);
console.log(msgBox);
const ws = new WebSocket("ws://localhost:8080");
button.addEventListener('click', function () {
// console.log(input.value)
let value = input.value
ws.send(value)
})
// ws事件监听
ws.addEventListener('open', function () {
console.log('连接成功了')
})
ws.addEventListener('message', function (e) {
console.log(e,'message')
let data = e.data;
let div = document.createElement('div')
div.innerHTML = `${data}`;
msgBox.appendChild(div)
input.value = ''
})
ws.addEventListener('close', function () {
console.log('连接关闭')
})
ws.addEventListener('error', function () {
console.log('连接异常')
})
</script>
</body>
</html>
const ws = require('nodejs-websocket');
// 记录当前连接上来多少个人
let count = 0;
const server = ws.createServer(connect => {
console.log('有用户连接上来了');
count++;
connect.userName = `用户${count}`
broadcast(`${connect.userName}进入了聊天室`);
connect.on('text', data => {
console.log('接收到了用户的数据', data);
// 2.2 给用户一个响应的数据
// connect.send(data);
broadcast(`${connect.userName}:${data}`);
})
// 2.3 用户关闭链接,只要websocket链接断开了就会触发这个事件
connect.on("close", function (code, reason) {
console.log("用户关闭链接")
broadcast(`${connect.userName}离开了聊天室`);
count--;
})
// 注册一个error,处理用户的报错信息
connect.on('error', () => {
console.log('用户连接异常')
})
})
// 广播消息
function broadcast(data) {
server.connections.forEach(item => {
item.send(data)
})
}
server.listen(8080, () => {
console.log('websocket服务启动成功了,监听了端口8080');
})
复杂聊天室
const ws = require('nodejs-websocket');
const TYPE_ENTER = 0; // 进入消息
const TYPE_LEAVE = 1; // 离开消息
const TYPE_MSG = 2; // 聊天消息
// 记录当前连接上来多少个人
let count = 0;
const server = ws.createServer(connect => {
console.log('有用户连接上来了');
count++;
connect.userName = `用户${count}`
broadcast({
type: TYPE_ENTER,
msg: `${connect.userName}:进入了聊天室`,
time: new Date().toLocaleTimeString()
})
connect.on('text', data => {
console.log('接收到了用户的数据', data);
// 2.2 给用户一个响应的数据
// connect.send(data);
// broadcast(`${connect.userName}:${data}`);
broadcast({
type: TYPE_MSG,
msg: `${connect.userName}:${data}`,
time: new Date().toLocaleTimeString()
})
})
// 2.3 用户关闭链接,只要websocket链接断开了就会触发这个事件
connect.on("close", function (code, reason) {
console.log("用户关闭链接")
// broadcast(`${connect.userName}离开了聊天室`);
broadcast({
type: TYPE_LEAVE,
msg: `${connect.userName}:离开了聊天室`,
time: new Date().toLocaleTimeString()
})
count--;
})
// 注册一个error,处理用户的报错信息
connect.on('error', () => {
console.log('用户连接异常')
})
})
// 广播消息
function broadcast(data) {
server.connections.forEach(item => {
item.send(JSON.stringify(data))
})
}
server.listen(8080, () => {
console.log('websocket服务启动成功了,监听了端口8080');
})
<!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>
<style>
#messagebox {
width: 300px;
height: 300px;
border: 1px solid #000;
}
</style>
</head>
<body>
<div>
<input type="text" placeholder="请输入您的消息" />
<button>发送消息</button>
<div id="messagebox"></div>
</div>
<script>
const TYPE_ENTER = 0; // 进入消息
const TYPE_LEAVE = 1; // 离开消息
const TYPE_MSG = 2; // 聊天消息
var input = document.querySelector('input');
var button = document.querySelector('button');
var msgBox = document.querySelector('#messagebox');
const ws = new WebSocket("ws://localhost:8080");
button.addEventListener('click', function () {
// console.log(input.value)
let value = input.value
ws.send(value)
})
// ws事件监听
ws.addEventListener('open', function () {
console.log('连接成功了')
})
ws.addEventListener('message', function (e) {
console.log(e, 'message')
let data = JSON.parse(e.data);
console.log(data);
let div = document.createElement('div')
div.innerHTML = `${data.msg}---${data.time}`;
if (data.type === TYPE_ENTER) {
div.style.color = 'green';
} else if (data.type === TYPE_MSG) {
div.style.color = 'blue'
} else {
div.style.color = 'red'
}
msgBox.appendChild(div)
input.value = ''
})
ws.addEventListener('close', function () {
console.log('连接关闭')
})
ws.addEventListener('error', function () {
console.log('连接异常')
})
</script>
</body>
</html>
聊天记录左右展示
自己右,其他人左
安装依赖
js npm install uuid
node部分代码
const ws = require('nodejs-websocket');
const { v4: uuidv4 } = require('uuid');
const TYPE_ENTER = 0; // 进入消息
const TYPE_LEAVE = 1; // 离开消息
const TYPE_MSG = 2; // 聊天消息
// 记录当前连接上来多少个人
let count = 0;
const server = ws.createServer(connect => {
console.log('有用户连接上来了');
count++;
connect.userName = `用户${count}`;
connect.uuid = uuidv4();
broadcast({
userName: connect.userName,
uuid: connect.uuid,
type: TYPE_ENTER,
msg: `${connect.userName}:进入了聊天室`,
time: new Date().toLocaleTimeString()
})
connect.on('text', data => {
console.log('接收到了用户的数据', data);
// 2.2 给用户一个响应的数据
// connect.send(data);
// broadcast(`${connect.userName}:${data}`);
broadcast({
userName: connect.userName,
uuid: connect.uuid,
type: TYPE_MSG,
msg: `${connect.userName}:${data}`,
time: new Date().toLocaleTimeString()
})
})
// 2.3 用户关闭链接,只要websocket链接断开了就会触发这个事件
connect.on("close", function (code, reason) {
console.log("用户关闭链接")
// broadcast(`${connect.userName}离开了聊天室`);
broadcast({
type: TYPE_LEAVE,
msg: `${connect.userName}:离开了聊天室`,
time: new Date().toLocaleTimeString()
})
count--;
})
// 注册一个error,处理用户的报错信息
connect.on('error', () => {
console.log('用户连接异常')
})
})
// 广播消息
function broadcast(data) {
server.connections.forEach(item => {
item.send(JSON.stringify(data))
})
}
server.listen(8080, () => {
console.log('websocket服务启动成功了,监听了端口8080');
})
html部分代码
根据ws监听拿到后端传递过来的数据,判断聊天进入离开的状态,给消息加上文字颜色,方便区分.
<!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>
<style>
#messagebox {
width: 400px;
height: 200px;
border: 1px solid #000;
overflow: auto;
}
.clearfloat:after {
display: block;
clear: both;
content: "";
visibility: hidden;
height: 0
}
.msg-right {
text-align: right;
}
.msg-left {
text-align: left;
}
</style>
</head>
<body>
<div>
<input type="text" placeholder="请输入您的消息" />
<button>发送消息</button>
<div id="messagebox" class="clearfloat"></div>
</div>
<script>
const TYPE_ENTER = 0; // 进入消息
const TYPE_LEAVE = 1; // 离开消息
const TYPE_MSG = 2; // 聊天消息
let flag = true;
var input = document.querySelector('input');
var button = document.querySelector('button');
var msgBox = document.querySelector('#messagebox');
const ws = new WebSocket("ws://localhost:8080");
button.addEventListener('click', function () {
// console.log(input.value)
let value = input.value
ws.send(value)
})
// ws事件监听
ws.addEventListener('open', function () {
console.log('连接成功了')
})
ws.addEventListener('message', function (e) {
// console.log(e, 'message')
let data = JSON.parse(e.data);
console.log(data);
let div = document.createElement('div')
div.style.marginBottom = '8px';
div.innerHTML = `${data.msg}---${data.time}`;
if (data.type === TYPE_ENTER) {
div.style.color = 'green';
if (flag) {
sessionStorage.setItem(data.uuid, data.userName)
flag = false
};
} else if (data.type === TYPE_MSG) {
div.style.color = 'blue'
let name = sessionStorage.getItem(data.uuid);
div.classList.add("msg-left");
if (data.userName === name) {
div.classList.remove("msg-left");
div.classList.add("msg-right");
}
} else {
div.style.color = 'red'
}
msgBox.appendChild(div)
input.value = ''
})
ws.addEventListener('close', function () {
console.log('连接关闭')
})
ws.addEventListener('error', function () {
console.log('连接异常')
})
</script>
</body>
</html>
绑定enter按键
通过监听body的键盘按下事件,判断 e.keycode值为13时(enter键)时,触发button按钮的事件 完成绑定键盘事件
<!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>
<style>
#messagebox {
width: 400px;
height: 200px;
border: 1px solid #000;
overflow: auto;
}
.msg-right {
text-align: right;
}
.msg-left {
text-align: left;
}
</style>
</head>
<body>
<div>
<input type="text" placeholder="请输入您的消息" />
<button>发送消息</button>
<div id="messagebox"></div>
</div>
<script>
const TYPE_ENTER = 0; // 进入消息
const TYPE_LEAVE = 1; // 离开消息
const TYPE_MSG = 2; // 聊天消息
var body = document.querySelector('body')
var input = document.querySelector('input');
var button = document.querySelector('button');
var msgBox = document.querySelector('#messagebox');
const ws = new WebSocket("ws://localhost:8080");
button.addEventListener('click', function () {
// console.log(input.value)
let value = input.value
input.value !== '' && ws.send(value)
})
body.addEventListener('keydown', function (event) {
if (input.value !== '' && event.keyCode === 13) {
button.click();
}
})
// ws事件监听
ws.addEventListener('open', function () {
console.log('连接成功了')
})
let flag = true;
ws.addEventListener('message', function (e) {
// console.log(e, 'message')
let data = JSON.parse(e.data);
console.log(data);
let div = document.createElement('div')
div.innerHTML = `${data.msg}---${data.time}`;
if (data.type === TYPE_ENTER) {
div.style.color = 'green';
if (flag) {
sessionStorage.setItem(data.uuid, data.userName)
flag = false;
}
} else if (data.type === TYPE_MSG) {
div.style.color = 'blue'
let name = sessionStorage.getItem(data.uuid)
div.classList.add("msg-left");
if (data.userName === name) {
div.classList.remove("msg-left");
div.classList.add("msg-right");
}
} else {
div.style.color = 'red'
}
msgBox.appendChild(div)
input.value = ''
})
ws.addEventListener('close', function () {
console.log('连接关闭')
})
ws.addEventListener('error', function () {
console.log('连接异常')
})
</script>
</body>
</html>
自动滚动聊天记录到底部
触发scrollIntoView 可以在发送消息满屏触底时,超出屏幕可以自动滚动到底部。
div.scrollIntoView({ block: "end", inline: "nearest", behavior: 'smooth' });