#webSocket的特点
websocket的特点之一是可以双向发数据,例如聊天场景,双方通信都是实时的,传统解决方案是使用轮询,即每一段时间发送一次请求给服务器,但是这种方式的缺点是占用资源,而websocket是协议层面的改变,让服务器可以向客户端主动发送消息,原理可以参考:
https://www.ruanyifeng.com/blog/2017/05/websocket.html
协议抓捕可以参考
https://www.likecs.com/show-662366.html
这里使用socket.io,实现一个聊天的Demo
后端:
let express = require("express");
let socket = require("socket.io");
let http = require("http");
let fs = require("fs")
let server = express()
// 静态化
server.use(express.static("./web/"))
let app = http.createServer(server);
let io = socket(app)
let usermsgs = [];
let users = []
io.on("connection", (client) => {
fs.readdir("./web/images", (err, result) => {
if (!err)
client.emit("Msg", 0, result)
} else {
client.emit("Msg", 1, "目录读取失败")
}
})
// 监听客户端加入
client.on("Newclient", (username) => {
// 1.存储用户
users.unshift([username.username, client]) // 存储用户名和当前客户端对象
// 2.广播消息 告诉其他用户,这个用户进入了俩天
io.emit("userlist", {
userlist: users.map(item => item[0])
})
// console.log("新加入", users.map(item => item[0]))
})
// 监听客户端离开
client.on("disconnect", () => {
// 1.删除用户
// users.indexOf([username.username, client])
let index = users.findIndex((item) => {
if (item[1] === client)
return true
})
if (index !== -1)
users.splice(index, 1) // 删除index
// 2.广播消息 告诉其他用户,这个用户进入了俩天
io.emit("userlist", {
userlist: users.map(item => item[0])
})
/// console.log("删除后", users.map(item => item[0]));
})
//监听客户端的文本消息
client.on("uerMsg", (...args) => {
console.log("消息", args[0], typeof args[0])
// 存消息
let newargs = args[0].replace(/\[(\w+)\]/gm, (...arge) => {
console.log("args", arge);
return ` <img src="/images/${arge[1]}.png" alt="" class="item">`;
})
usermsgs.push([newargs, args[1], , client])
// 公告消息
io.emit("userMsgs", usermsgs.map(item => [item[0], item[1]]))
})
})
app.listen(3000, () => console.log("服务器启动成功"))
其中 io.on(“connection” ,) 这个是表示监听链接的客户端,是内置的事件
client.on(“disconnect”,)这个表示监听客户端离开,是内置事件
其他的on监听事件,是自定义的和客户端相对应
前端:
io.emit(“userMsgs”, usermsgs.map(item => [item[0], item[1]])) 表示广播给所有客户端
<script src="/socket.io/socket.io.js"></script>
<script>
// 发送socket请求
let socket = io();
// 监听浏览器与服务器连接
socket.on("connect", function (...args) {
// 连接成功后就直接
let username = prompt("请输入用户名") || "匿名用户";
document.querySelector(".username").innerHTML = `<h1>${username}</h1>`
// 发送消息
socket.emit("Newclient", {
"username": username
})
btn.addEventListener("click", (e) => {
// console.log(text.value)
if (text.value.length > 0) {
socket.emit("uerMsg", text.value, username)
} else {
alert("没有输入内容")
}
})
})
// 监听消息 写咋连接的外面
socket.on("Msg", (...args) => {
let str = "";
for (let i = 0; i < args[1].length; i++) {
str += `<img src="/images/${args[1][i]}" alt="" class="item">`
}
document.querySelector(".img-list").innerHTML = str;
// 给每一个图片设置一个点击事件
let imgs = document.querySelectorAll(".item")
for (let i = 0; i < imgs.length; i++) {
imgs[i].addEventListener("click", () => {
//console.log(imgs[i].src.match(/\/(\w+)\./));
text.value += `[${imgs[i].src.match(/\/(\w+)\./)[1]}]`
})
}
})
//监听人数
// 监听消息 连接可以写在外面
socket.on("userlist", (args) => {
console.log(args)
let str = "";
for (let i = 0; i < args.userlist.length; i++) {
str += `<li class="list-group-item">${args.userlist[i]}</li>`
}
console.log("xx", str)
document.querySelector(".userlist").innerHTML = str;
})
// 监听用户消息
socket.on("userMsgs", (args) => {
console.log("全部用户消息", args)
let str = "";
for (let i = 0; i < args.length; i++) {
str += `<li class="list-group-item">${args[i][1]} : ${args[i][0]}</li>`
}
// console.log("xx", str)
document.querySelector(".ly").innerHTML = str;
})
</script>