服务入口文件
// IOT服务
const iot = require("./iot/runtime");
const iotInstance = new iot(require("./config").runMode, 2000); //production or development
iotInstance.run();
// koa服务
const Koa = require("koa");
const app = new Koa();
// 解决跨域问题
const cors = require("./utils/cors");
app.use(cors);
// 通过koa内部封装好的上下文进行判断处理get、post、html页面
app.use(async (ctx: any, next: any) => {
const { url, method } = ctx;
console.log(666.999, url, method);
// 前端调用示例:const value = await axios.post('http://127.0.0.1:9098/users');
const getLists = ["/get", "/user/get", "/users"];
const postLists = ["/post", "/user/post", "/users"];
if (url.startsWith("/socket")) {
console.log(666.456, "进入ws通信", url, method);
await next();
} else if (method === "GET" && getLists.includes(url)) {
// 当GET请求时候的处理
ctx.body = "get test" + url;
} else if (method === "POST" && postLists.includes(url)) {
// post请求的处理
ctx.body = "post test" + url;
} else {
// 除了以上的数据特殊处理请求外,均执行dist文件包to网站服务
const path = require("path");
// 加载html页面或ejs、pug模板等
const Views = require("koa-views");
app.use(
Views(path.join(__dirname, "../web-client-dist/ui"), {
extension: "html",
// map: { html: "html" },
})
);
// 静态资源加载
const Static = require("koa-static");
app.use(Static(path.join(__dirname, "../web-client-dist/ui")));
// 继续执行接下来的服务*必须
await next();
}
});
// nodejs启动http服务
const http = require("http");
const server = http.createServer(app.callback());
// websocket服务
const Socket = require("socket.io");
const io = Socket(server, {
allowEIO3: true,
// cors: true,
cors: {
origin: "*", // WS跨域,DEV调试的时候需要,示例:http://localhost:909
methods: ["GET", "POST"],
},
});
const sockets: any[] = [];
io.on("connection", (socket: any) => {
console.log("socket conncet,id is:", socket.id);
sockets.push(socket);
socket.on("msg-client", (msg: string) => {
console.log("client msg:", msg);
socket.emit("msg-server", { msg: msg }, (res: any) => {
console.log(666.329, res);
});
});
socket
.timeout(5000)
.emit("timeout", "hello world", (err: any, response: any) => {
if (err) {
// 另一方未在给定延迟内确认事件
} else {
console.log(response); // "got it"
}
});
socket.on("disconnect", () => {
console.log("user disconnected" + socket.id);
});
});
io.on("disconnect", () => {
console.log("disconnect");
});
let indexNum: number = 1;
setInterval(() => {
indexNum++;
io.emit("msg", iotInstance.Model);
io.emit("msg-index", indexNum);
// console.log(
// sockets.map((item) => {
// return {
// id: item.id,
// connect_status: item.connected,
// };
// })
// );
}, 1000);
//nodejs服务启动,包含http及ws
const { APP_PORT } = require("./config/config.default");
server.listen(APP_PORT, function () {
console.log("server is running on http://127.0.0.1:" + APP_PORT);
});
跨域封装文件
// const REG_WHITE_LIST = /^https?:\/\/(?:[0-9a-zA-Z-]+\.)*\.(?:ws|biz|com)(?::\d+)?$/;// 正则方式匹配 REG_WHITE_LIST.test(origin)
const REG_WHITE_LIST = ["http://127.0.0.1:909", "http://127.0.0.1:9098"];
// 这里写上想要匹配的域名
module.exports = async (ctx: any, next: any) => {
const origin = ctx.request.header.origin;
// const origin = ctx.get("Origin");
console.log(
666.789,
Date.now(),
ctx.request.header.origin,
REG_WHITE_LIST.includes(origin)
);
if (origin && REG_WHITE_LIST.includes(origin)) {
ctx.set("Access-Control-Allow-Origin", origin); // 允许跨域
ctx.set("Access-Control-Allow-Methods", "POST,GET,OPTIONS,HEAD,PUT,DELETE"); // 支持的方法
ctx.set("Access-Control-Allow-Credentials", "true"); // 允许传入Cookie
ctx.set("Access-Control-Max-Age", 2592000); // 过期时间一个月
// 如果有特殊的请求头,直接响应
if (ctx.get("Access-Control-Request-Headers")) {
ctx.set(
"Access-Control-Allow-Headers",
ctx.get("Access-Control-Request-Headers")
);
}
// FIX:浏览器某些情况下没有带Origin头
ctx.set("Vary", "Origin");
// 如果是 OPTIONS 请求,则直接返回
if (ctx.method === "OPTIONS") {
ctx.status = 204;
return;
}
}
await next();
};
socket.io客户端示例
<script setup lang="ts">
import opt1 from './charts/multipleLines';
import * as echarts from 'echarts';
import { getCurrentInstance, onMounted, reactive, ref } from 'vue';
import axios from 'axios';
import { io } from 'socket.io-client';
const socket = io('ws://127.0.0.1:9098');
const data1 = reactive({
time: ['1', '2'],
voltage: [380, 370],
current: [100, 110],
});
const indexstr = ref('');
const data2: any[] = reactive([]);
const panel = ref();
const $echarts = echarts;
const ioServerCount = ref(1);
const ioServerMsg = ref('');
function sendMsg(msg: string) {
ioServerCount.value++;
console.log(666.333, ioServerCount.value + ': ' + msg);
socket.emit('msg-client', ioServerCount.value + ': ' + msg);
}
onMounted(() => {
const myChart1 = $echarts.init(panel.value);
myChart1.setOption(opt1(data1));
socket.on('connect', () => {
console.log('connect');
});
socket.on('msg-server', (msg: { msg: string }, callback) => {
ioServerMsg.value = msg.msg;
callback('got it');
});
socket.on('msg-index', (msg: string) => {
indexstr.value = msg;
});
socket.on('msg', (data: any) => {
data1.time.push(data.voltage.update);
data1.voltage.push(data.voltage.value);
data1.current.push(data.current.value);
if (data1.time.length > 5) {
data1.time.shift();
data1.voltage.shift();
data1.current.shift();
}
myChart1.setOption(opt1(data1));
data2.push(data);
if (data2.length > 5) {
data2.shift();
}
});
});
const apimsg = ref('');
async function apiMsg(type: number) {
// apimsg.value = await axios.get('http://127.0.0.1:3333/page/helloworld');
// apimsg.value = await axios.get('http://127.0.0.1:3333/users/login');
if (type === 1) {
apimsg.value = await axios.get('http://127.0.0.1:9098/users');
} else if (type === 2) {
apimsg.value = await axios.post('http://127.0.0.1:9098/users');
} else if (type === 3) {
apimsg.value = await axios.post('http://127.0.0.1:9098/socket.io');
} else if (type === 4) {
apimsg.value = await axios.post('http://127.0.0.1:9098/');
}
}
</script>
<template>
<h1>Socket.IO预研{{ indexstr }}</h1>
<el-button @click.stop="apiMsg(1)">API1</el-button>
<el-button @click.stop="apiMsg(2)">API2</el-button>
<el-button @click.stop="apiMsg(3)">API3</el-button>
<el-button @click.stop="apiMsg(4)">API4</el-button>
{{ apimsg }}
<div class="dangger">aaa</div>
<div class="bg">
<div id="panel" ref="panel"></div>
<div ref="panel2" id="panel2">
<p v-for="(item, index) in data2" :key="index">
<!-- {{item}} -->
<span>{{ new Date(item.voltage.update) }}</span>
{{ item.voltage.des }}:{{ item.voltage.value }}
{{ item.current.des }}:{{ item.current.value }} {{ item.speed.des }}:{{
item.speed.value
}}
<!-- {{item.voltage.des}}:{{item.voltage.value}} -->
</p>
</div>
</div>
---123
<div>
<el-button @click.stop="sendMsg('发送消息1')" type="primary">
发送消息1
</el-button>
<el-button @click.stop="sendMsg('test1')">test1</el-button>
接收的服务器消息:{{ ioServerMsg }}
</div>
</template>
<style scoped lang="scss">
.bg {
background-color: bisque;
}
#panel {
width: 400px;
height: 300px;
}
#panel2 {
width: 400px;
height: 300px;
p {
display: block;
border: solid 1px #003366;
margin: 0;
span {
display: block;
}
}
}
</style>