WebSocket
很多网站为了实现推送技术,所用的技术都是轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。
而比较新的技术去做轮询的效果是Comet。这种技术虽然可以双向通信,但依然需要反复发出请求。而且在Comet中,普遍采用的长链接,也会消耗服务器资源。
在这种情况下,HTML5定义了WebSocket协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。
使用 WebSocket,还可以实现浏览器内多个标签页之间的通信,通信的标签页连接同一个服务器,发送消息到服务器后,服务器推送消息给所有连接的客户端。
聊天室
登录时使用缓存记录下用户名
sessionStorage.setItem('user', this.form.username)
聊天室代码
<template>
<div align="center">
<el-row style="width: 50%;">
<!-- 用户列表-->
<el-col :span="6">
<el-card style="width: 100%;height: 800px">
<div style="text-align: center;font-size: 28px;margin-bottom: 10px">当前聊天室成员</div>
<div style="height: 700px;overflow-y:auto;border:1px solid #000000;border-radius: 5px">
<div v-for="(item,index) in userList" :key="index" style="padding: 10px;margin-top: 10px;font-size: 20px">
{{item}}
</div>
</div>
</el-card>
</el-col>
<!-- 聊天室-->
<el-col :span="18">
<div style="width: 100%;">
<el-card style="width: 100%;height: 800px">
<div style="text-align: center;font-size: 28px;margin-bottom: 10px">一起聊天吧</div>
<div style="width: 100%;height: 550px;border:1px solid #000000;border-radius: 5px;overflow-y:auto;margin-bottom: 10px">
<div v-for="(item,index) in msgList" :key="index">
<!-- {{item.from}}{{item.msg}}{{item.time}}-->
<div align="right" v-if="item.from===user" style="color: dodgerblue">{{item.time}} {{item.msg}}<el-tag size="mini">{{item.from}}</el-tag></div>
<div align="left" v-else style="color: coral"><el-tag size="mini" type="danger">{{item.from}}</el-tag>{{item.msg}} {{item.time}}</div>
</div>
</div>
<el-input @keyup.enter.native="send" type="textarea" v-model="message.msg" :autosize="{ minRows: 2, maxRows: 4}" placeholder="请输入聊天内容"></el-input>
<div align="right">
<el-button type="primary" style="margin-top: 10px" @click="send">发送</el-button>
</div>
</el-card>
</div>
</el-col>
</el-row>
</div>
</template>
<sc
name: 'chat',
data() {
return {
// 登录用户
user: '',
// 消息记录列表
msgList: [],
// 发送的消息
message: {
time:null,//时间
to: '',//发给谁
from: '',
msg: ''
},
// 在线用户列表
userList: []
}
},
methods: {
init() {
// 如果sessionStorage中没有用户信息,则跳转登录页面
this.user = sessionStorage.getItem('user')
if (!this.user) {
this.$router.push('/')
}
let that = this;
if (typeof (WebSocket) == "undefined") {
console.log("您的浏览器不支持WebSocket");
} else {
console.log("您的浏览器支持WebSocket");
//服务器地址
let socketUrl = "ws://localhost:8888/socket/" + this.user;
if (ws != null) {
ws.close();//关闭连接
ws = null;
}
// 开启一个websocket服务
ws = new WebSocket(socketUrl);
//打开事件
ws.onopen = function () {//服务器连接成功
console.log("websocket已打开");
};
// 浏览器端收消息,获得从服务端发送过来的文本消息
ws.onmessage = function (msg) {//解析信息
console.log("收到数据====" + msg.data)
let data = JSON.parse(msg.data)
if (data.userNames) {
// userNames存在则是有人登录,获取在线人员信息
that.userList = data.userNames
} else {
// userNames不存在则是有人发消息
that.msgList.push(data)
}
};
//关闭事件
ws.onclose = function () {//服务器连接关闭
console.log("websocket已关闭");
};
//发生了错误事件
ws.onerror = function () {//服务器连接出错
console.log("websocket发生了错误");
}
}
},
//点击发送事件
send() {
if (!this.message.msg) {
this.$message({
message: '大兄弟,请输入聊天消息!',
type: 'warning'
});
} else {
if (typeof (WebSocket) == "undefined") {
console.log("您的浏览器不支持WebSocket");
} else {
console.log("您的浏览器支持WebSocket");
this.message.from=this.user;
this.message.time=new Date().toLocaleTimeString();
ws.send(JSON.stringify(this.message));//发送请求
this.message.msg = '';
}
}
}
},
mounted() {
this.init()
}
}
</script>
一些属性
ws.readyState
// 0 正在链接中
// 1 已经链接并且可以通讯
// 2 连接正在关闭
// 3 连接已关闭或者没有链接成功
ws.url
// 是一个只读属性
//返回构造函数创建WebSocket实例对象时URL的绝对路径。