WebSocket 服务器
express
配置主路由
/*
* 2022/11 powered by shuke
* version 2.0
* */
const express = require("express");
const path = require("path");
const bodyParser = require("body-parser"); //中间件
const apiRouter = require("./routes/apiRouter");
const {jwtAuth} = require("./utils/auth.config");
const config=require("./config")
//express 实例化
app = express();
app.use(bodyParser.urlencoded({extended: false})); //路由解码
app.use(bodyParser.json()); //实例使用中间件
app.use(express.static(path.join(__dirname, config.static))) //功能:用户可直接访问
//跨域(协议,域名,端口号)
app.all("*", function (req, res, next) {
//设置允许跨域的域名,*代表允许任意域名跨域
res.header("Access-Control-Allow-Origin", "*");
//允许的header类型
res.header("Access-Control-Allow-Headers", "content-type,Authorization");
//跨域允许的请求方式
res.header("Access-Control-Allow-Methods", "DELETE,PUT,POST,GET,OPTIONS");
//指定本次预检请求的有效期,单位秒,在此期间不用发出另一条预检请求。
res.setHeader("Access-Control-Max-Age", "3600");
next();
});
// 配置CORS跨域资源共享
// const cors = require('./utils/corsUtil.config.js');
// app.use(cors);
//token 验证处理err
app.use(jwtAuth, (err, req, res, next) => {
try {
if (err) {
res.status(401).json({data: err, status: false});
} else {
next()
}
} catch (e) {
res.status(401).json({data: e, status: false});
}
})
const expressWS=require("express-ws");
const wsRouter=require("./routes/wsRouter")
expressWS(app);
app.use('/ws', wsRouter);
app.use(config.api, apiRouter)
.use((req, res) => { //错误重定向 res.redirect(404,"back")
try {
res.status(404).json({data: "这个接口没有找到!", status: false});
} catch (e) {
res.status(500).json({data: e.message, status: false});
}
});
app.listen(config.port, config.address, function (err, res) {
console.log(err?err:"server run http://localhost:"+config.port)
})
配置子路由
const express = require("express");
const WebSocket = require('ws');
const expressWS = require("express-ws");
expressWS(express());
const router = express.Router();
const M = require("../models/MModel");
function fmtData(msg, type = 1, status = true) {
return JSON.stringify({
data: msg,
type,
status,
});
}
async function coutTabel() {
return {
user: await M.Total("user"),
cate: await M.Total("cate"),
movies: await M.Total("movies"),
cinema: await M.Total("cinema"),
session: await M.Total("session"),
order: await M.Total("order"),
};
}
router
.ws("/root", async function (ws, req) {
console.log("server启动,已经建立连接。。。");
// 使用 ws 的 send 方法向连接另一端的客户端发送数据
// ws.send(fmtData('server:欢迎访问服务器'))
ws.send(fmtData(await coutTabel(), 2));
// 使用 on 方法监听事件
// message 事件表示从另一段(服务端)传入的数据
ws.on("message", function (msg) {
const obj = JSON.parse(msg);
console.log(`收到信息:`, obj);
if (obj.num) {
clearInterval(timer);
timer = setInterval(async () => {
ws.send(fmtData(await coutTabel(), 2));
}, obj.num * 1000);
}
});
// 设置定时发送消息
let timer = setInterval(async () => {
ws.send(fmtData(await coutTabel(), 2));
}, 10000);
// close 事件表示客户端断开连接时执行的回调函数
ws.on("close", function (e) {
console.log("链接关闭");
clearInterval(timer);
timer = undefined;
});
});
let clients = [];
let users=[]
router.ws("/chart", async function (ws, req) {
clients.push(ws); // 添加新的连接到clients数组
ws.on("message", function (msg) {
console.log(msg)
// 当收到消息时,将其广播到所有连接的客户端
clients.forEach(client => {
console.log(client !== ws,client.readyState === WebSocket.OPEN);
if (client !== ws && client.readyState === WebSocket.OPEN) {
client.send(fmtData({data: msg}, 2));
}
});
});
ws.on("close", function (e) {
console.log("链接关闭");
// 移除关闭的连接
clients = clients.filter(client => client !== ws);
ws.send(fmtData({ data: "链接关闭" }, 1));
});
});
module.exports = router;
客户端 自动更新
/ws/root
混入
import {Message} from "element-ui"
export default {
data() {
return {
interval:10,
list: null,
ws: null,
updateNum:0
}
},
computed: {
wsOpen(){
return Boolean(this.ws)
}
},
methods: {
connect() {
if (this.ws) {
this.closeConnect();
}
this.ws = new WebSocket("ws://127.0.0.1:5500/ws/root");
const {ws} = this;
ws.onopen = () => {
console.log("连接成功", ws);
Message.success("WebSocket连接成功")
};
ws.onmessage = (evt) => {
console.log("Message received: ", evt.data);
const res = JSON.parse(evt.data)
if (res.type == 2) {
this.updateNum++;
if(JSON.stringify(res.data)!=JSON.stringify(this.list)){
this.list = res.data;
}
}
};
ws.onclose = () => {
console.log("完成关闭");
Message.info("WebSocket完成关闭")
this.ws = null;
this.updateNum=0;
};
},
sendMessage() {
const {ws} = this;
if (ws && ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({num:this.interval}));
} else {
// console.log("Not connected or connection is closing or closed");
Message.error("服务器连接失败")
}
},
closeConnect() {
this.ws.close();
}
},
beforeUnmount() {
this.closeConnect()
}
}
组件
<template>
<el-card class="margin">
<div slot="header">
<div class="float-right">
<el-switch
:value="wsOpen"
active-color="#13ce66"
inactive-color="#ff4949">
</el-switch>
</div>
<span>WebSocket 案例</span>
</div>
<el-button-group>
<el-button type="success"
:loading="wsOpen"
@click="connect">{{ws?'更新'+updateNum:'连接'}}</el-button>
</el-button-group>
<el-button-group v-show="wsOpen" class="float-right">
<el-button type="danger" @click="closeConnect">断开</el-button>
<el-input-number v-model="interval" :min="1" :max="100"></el-input-number>
<el-button type="primary" @click="sendMessage">设置</el-button>
</el-button-group>
<el-row class="text-center" v-if="list">
<el-col v-for="(value,key) in list" :key="key" :span="8">
<el-card class="margin">
<h1>{{value}}</h1>
<h3>{{key}}</h3>
</el-card>
</el-col>
</el-row>
</el-card>
</template>
<script>
import ws from "../mixins/ws.js"
export default {
name: "wsCom",
components: {}, //加载子组件
mixins: [ws],
}
</script>
客户端 聊天室
/ws/chart
混入
import {Message} from "element-ui"
export default {
data() {
return {
msg:"hello "+new Date(),
list:[],
user:{name:""},
ws: null,
}
},
computed: {
wsOpen(){
return Boolean(this.ws)
}
},
methods: {
connect() {
if (this.ws) {
this.closeConnect();
}
this.ws = new WebSocket("ws://127.0.0.1:5500/ws/chart");
const {ws} = this;
ws.onopen = () => {
console.log("连接成功", ws);
Message.success("WebSocket连接成功")
};
ws.onmessage = (evt) => {
console.log("Message received: ", evt.data);
const res = JSON.parse(evt.data)
if (res.type == 2) {
this.list = [...this.list,JSON.parse(res.data.data)];
this.$nextTick(()=>{
//this.$refs.box.scrollTop=this.$refs.box.scrollHeight
})
}
console.log(this.$refs.box)
};
ws.onclose = () => {
console.log("完成关闭");
Message.info("WebSocket完成关闭")
this.ws = null;
this.list=[]
};
},
sendMessage() {
if (!this.msg){return}
const {ws} = this;
if (ws && ws.readyState === WebSocket.OPEN) {
const obj={msg:this.msg,user:{...this.user},date:+new Date()}
this.list = [...this.list,obj];
ws.send(JSON.stringify(obj));
} else {
Message.error("服务器连接失败")
}
},
closeConnect() {
this.ws.close();
}
},
beforeUnmount() {
this.closeConnect()
}
}
组件
<template>
<el-card class="margin">
<div slot="header">
<div class="float-right">
<el-button size="mini" type="success" @click="list=[]">清空</el-button>
<el-button size="mini" type="danger" @click="closeConnect" v-if="wsOpen">退出</el-button>
</div>
<span>在线聊天室 <strong>{{user.name}}</strong></span>
<el-switch :value="wsOpen"></el-switch>
</div>
<div class="padding-y">
<el-input v-model="user.name" v-if="!ws">
<el-button slot="append" @click="connect" :loading="!Boolean(user.name)"> 加入</el-button>
</el-input>
</div>
<div >
<ul v-if="list.length" style="max-height: 400px;padding:0 2em;overflow: auto" ref="box" id="box">
<li v-for="(item,index) in list" :key="index" class="padding-y ">
<div :class="user.name==item.user.name?'text-right':''">
<el-badge :value="index+1" type="primary">
<el-button size="small">
{{item.user.name}} -
{{item.date|setDateTime}}
</el-button>
</el-badge>
</div>
<el-alert :closable="false" :title="item.msg"></el-alert>
</li>
</ul>
</div>
<div class="" v-if="wsOpen" >
<el-input v-model="msg">
<el-button slot="append" @click="sendMessage"> 发送</el-button>
</el-input>
</div>
</el-card>
</template>
<script>
import chat from "../mixins/chat.js"
export default {
name: "chartCom",
components: {},
mixins: [chat],
data() {
return {}
},
}
</script>
最新回复 (0)
全部楼主