前言
目前很多项目需要用到websocket功能
简单的讲解一下这个功能。
简单来说就是,以往我们发请求只能前台给后台发
但是如果我们遇到比如类似聊天一样的功能,别人发信息给我。
我们就处理起来很麻烦,当然也有办法,就是我们前端设置定时器
定时请求后台拿到别人发给我的信息。
但是很明显,这不是一个好办法,如果一秒一请求,那服务器顶不住,毕竟用户不是你一个。
如果间隔时间久了,那别人发个信息给你,你都半天看不到,那还有人用你的软件吗。
所以这时候就出现了websocket。他可以让前端和后端建立长链接。保持通信状态。
不需要前端发请求,后端也可以自己把别人发来的信息推送到你前台。这就是方便多了。
看了网上很多人的帖子都是只有单独的,所以我这里再开一个前后端都有的websocket模板,可以复制即用,后端采用了node.js这样方便前端的小伙伴看得懂。而且很简单操作,复制了就可以自己测试websocket功能,不需要依靠公司后端了。
效果图
心跳后端返回ok
心跳
我发送的信息后端返回给我了。
心跳重连机制,如果链接失败或者错误,一直重连,直到链接成功为止
前端代码
<template>
<!-- websocketceshi -->
<div class="layout">
<div style="margin:20px;font-size:20px">websocket连接模板 有心跳重连机制</div>
<div class="msgBody">
<p v-for="(item, index) in msg" :key="index">{{ item }}</p>
</div>
<input
v-model="inputMsg"
style="width: 200px; height: 30px; margin-top: 20px"
/>
<button @click="sendMessage" style="width: 100px; height: 30px">
发送
</button>
<button @click="msg = []" style="width: 70px; height: 30px">清空</button>
</div>
</template>
<script>
export default {
name: "LayOut",
data() {
return {
ws: null, //建立的连接
lockReconnect: false, //是否真正建立连接
timeout: 10 * 1000, //30秒一次心跳
timeoutObj: null, //心跳心跳倒计时
serverTimeoutObj: null, //心跳倒计时
timeoutnum: null, //断开 重连倒计时
wsUrl: "ws://localhost:8888", //后台websocket连接地址
msg: [], //信息列表
inputMsg: "", //输入
};
},
created() {
this.initWebpack();
},
beforeDestroy() {
// 离开页面后关闭连接
this.ws.close();
// 清除时间
clearTimeout(this.timeoutObj);
clearTimeout(this.serverTimeoutObj);
},
methods: {
// 初始化websocket链接
initWebpack() {
this.ws = new WebSocket(this.wsUrl);
this.ws.onopen = this.onopen;
this.ws.onmessage = this.onmessage;
this.ws.onclose = this.onclose;
this.ws.onerror = this.onerror;
},
//重新连接
reconnect() {
var that = this;
if (that.lockReconnect) {
return;
}
that.lockReconnect = true;
//没连接上会一直重连,设置延迟避免请求过多
that.timeoutnum && clearTimeout(that.timeoutnum);
that.timeoutnum = setTimeout(function () {
that.initWebpack(); //新连接
that.lockReconnect = false;
}, 5000);
},
//重置心跳
reset() {
var that = this;
clearTimeout(that.timeoutObj); //清除心跳倒计时
clearTimeout(that.serverTimeoutObj); //清除超时关闭倒计时
that.start(); //重启心跳
},
//开启心跳
start() {
var self = this;
self.timeoutObj && clearTimeout(self.timeoutObj); //心跳倒计时如果有值就清除掉,防止重复
self.serverTimeoutObj && clearTimeout(self.serverTimeoutObj); //超时关闭倒计时如果有值就清除掉,防止重复
//然后从新开一个定时器
self.timeoutObj = setTimeout(function () {
//这里通过readyState判断链接状态,有四个值,0:正在连接,1:已连接,2:正在断开,3:已经断开或者链接不成功
if (self.ws.readyState == 1) {
//如果连接正常,给后天发送一个值,可以自定义,然后后台返回我们一个信息,我们接收到后会触发onmessage方法回调
self.ws.send("ping");
} else {
//如果检测readyState不等于1那也就代表不处在链接状态,那就是不正常的,那就调用重连方法
self.reconnect();
}
//从新赋值一个超时计时器,这个定时器的作用:当你触发心跳的时候可能会出现一个情况,后台崩了,前台发了个心跳,没有回应,就不会触发onmessage方法
//所以我们需要在这个心跳发送出去了后,再开一个定时器,用于监控心跳返回的时间,比如10秒,那么10秒内如果后台回我了,触发onmessage方法,自然就会把心跳时间和超时倒计时一起清空掉
//也就不会触发这个关闭连接,但是如果10秒后还是没有收到回应,那么就会触发关闭连接,而关闭连接方法内又会触发重连方法,循环就走起来了。
self.serverTimeoutObj = setTimeout(function () {
//如果超时了就关闭连接
self.ws.close();
}, self.timeout);
}, self.timeout);
},
//连接成功
onopen() {
console.log("连接成功");
if (this.ws.readyState == 1) {
//如果连接正常,给后天发送一个值,可以自定义,然后后台返回我们一个信息,我们接收到后会触发onmessage方法回调
this.ws.send("链接成功后先发给后台的信息");
}
this.start(); //链接成功后开启心跳
},
//接受后台信息回调
onmessage(e) {
/**这里写自己的业务逻辑代码**/
this.msg.push(e.data);
console.log("收到后台信息");
this.reset(); //收到服务器信息,心跳重置
},
//关闭连接回调
onclose(e) {
console.log("连接关闭");
this.reconnect(); //重连
},
//连接异常回调
onerror(e) {
console.log("出现错误");
this.reconnect(); //重连
},
//发送消息
sendMessage() {
this.ws.send(this.inputMsg); //把前台的信息发给后台(可以跟后端商量传什么数据结构,一般不是这样简单的一个字符串,都是json格式的)
this.inputMsg = "";
},
},
};
</script>
<style scoped>
.layout {
position: relative;
width: 100%;
height: 100%;
}
.msgBody {
width: 500px;
height: 300px;
border: 1px solid rgb(95, 79, 79);
overflow: auto;
}
</style>
后端部分项目创建
没有下载node的下载一下,没有淘宝镜像的可以下载一下淘宝镜像,方便后面下载。
1.安装node.js,自行官网下载,前端人员应该都有下载node。如果要看是否下载直接cmd输入 node –v查看版本
2.安装cnpm 安装命令 :npm install -g cnpm —registry=https://registry.npm.taobao.org
然后按照步骤来:
1,创建一个文件夹,然后在里面写一个文件,名字叫 express–run.js 把这个代码复制进去就行了,这个代码包含了get和post请求,以及websocket。所以前端小伙伴也可以用这个后台测试一下接口
var express = require("express"); //导入express (下载)
var app = express();
var bodyParser = require("body-parser"); //导入body-parser (下载)
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
// 跨域设置
var allowCrossDomain = function (req, res, next) {
res.header('Access-Control-Allow-Origin', '*'); //自定义中间件,设置跨域需要的响应头。
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, DELETE'); //允许任何方法
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type,X-Session-Token'); //允许任何类型
next();
};
app.use(allowCrossDomain);
//模拟信息
dataInfo = [
{ name: "苹果", count: 0, price: 10.01, check: false, },
{ name: "桃子", count: 0, price: 22.11, check: false, },
{ name: "橘子", count: 0, price: 8.12, check: false, },
]
//get方法 前台请求地址:http://127.0.0.1:3000/list/fruitsData
app.get('/list/fruitsData', (req, res) => {
res.status(200),
res.send({ code: 200, describe: "success", data: dataInfo })
})
//post方法 前台请求地址:http://127.0.0.1:3000/user/login
app.post('/user/login', (req, res) => {
var { username, password } = req.body
console.log(req.body);
if (username != "xq" || password != "xq123") {
return res.send({ code: 404, describe: "用户名或密码不正确" })
} else {
return res.send({ code: 200, describe: "success", data: { username, password } })
}
})
//websocket
const WebSocketServer = require('ws').Server
const wss = new WebSocketServer({ port: 8888 }) //服务端口8888
var player = new Array()
console.log('创建ws服务', 'ws://localhost:8888')
// 创建连接
wss.on("connection", ws => {
id = gid();
player.push(id)
console.log("新客户端已连接")
// 接收到 client 数据时
ws.on("message", data => {
//前台传ping就返回ok
if (data == 'ping') {
ws.send('ok')
return
}
//群发
wss.clients.forEach(s => {
if (s.readyState == 1 && s.socketIdxos != id) {
s.send(data)
}
})
})
ws.on("close", () => {
console.log("websocket server: 客户端已关闭连接")
player = new Array()
})
ws.onerror = function () {
console.log("websocket server: 出错了")
}
})
//给用户设定一个id
function gid() {
var id = Math.floor(Math.random() * (99999999 - 10000000 + 1)) + 10000000
var have = false;
for (var i = 0; i < player.length; i++) {
if (player[i] == id.toString()) {
have = true;
break;
}
}
if (have) {
gid();
} else {
return id;
}
}
const port = process.env.PORT || 3000 //端口
const host = process.env.HOST || '127.0.0.1' //地址
//运行中
app.listen(port, host, () => {
console.log(`Server is running on http://127.0.0.1:3000`);
});
2,安装依赖 cnpm install -S express body-parser
3,安装package.json 安装命令 npm init -y
启动方式:和前端启动方式一样,这里一般默认的是start 那你启动就npm run start
但是我改成了dev,这是我的习惯,所以我的启动方式就是npm run dev
然后当下面出现了Server is running on http://127.0.0.1:3000这句话就代表后台启动成功正在运行了,这句话是log出来的,可以自己改别的也行。
如果你想结束运行,也是和前台一样ctrl+c按两下就行。
这是项目的结构
原文地址:https://blog.csdn.net/seeeeeeeeeee/article/details/127323888
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_44988.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!