一些关于webscoket的小知识
- webscoket可以使得客户端和服务器联系更加简单,只需要一次握手,就可以实现持久性连接,服务器就能主动向客户端发送消息。
- webscoket和http一样,都是在OSI模型的最高层:应用层
- 相对于http来说,http每次请求都需要携带完整的请求头部,真正有效的内容只有一小部分,这样会浪费掉很多带宽,而webscoket,客户端和服务器进行数据交互的时候,服务器端到客户端的包头只有2-10个字节,客户端到服务器端要另外携带4字节的掩码,数据格式轻量,性能开销小,实时性更好
- 应用场景: 数据实时更新,聊天室…
下面就开始封装webscoket
服务器端
在vue项目根目录中
新建一个文件夹 server
新建项目文件 index.js
在该文件夹中 进行初始化 npm init - y
安装对应的npm包 npm i ws
// server/index.js 文件内容
const Ws = require('ws')
((WS) => {
const server = new WS.Server({port:3000}) // 生成服务 监听端口号
// 初始化
const init = ()=>{
bindEvent()
}
function bindEvent(){
// 绑定相关的事件处理fn
server.on('open',handleOpen)
server.on('close',handleClose)
server.on('error',handleError)
server.on('connection',handleConnection)
}
function handleOpen(){
console.log('BE: WEBSCOKET OPEN')
}
function handleClose(){
console.log('BE: WEBSCOKET CLOSE')
}
function handleError(){
consloe.log('BE WEBSCKOET ERROR')
}
function handleConnection(ws){
// 这个函数里有一个ws的实例对象
// 实例对象中会有处理客户端返回过来的数据的function
// 叫做message
console.log('BE WEBSCOKET CONNERTION')
ws.on('message',handleMessage)
}
function handleMessage(msg){
// 这个函数是用来处理客户端发送过来的
// 处理客户端的数据…
console.log(msg.toString())
// 分发处理好的数据
server.clients.forEach((c)=>{
c.send(msg.toString())
})
}
// 这样服务器端就封装完了
)(WS)
客户端
在vue项目的src目录中
新建webscoket文件夹,在文件夹下 新建 scoket.js 文件
// scoket.js 文件
const WsUrl = "ws://localhost:3000" // 连接地址 端口号要和服务端监听的端口号一致
// 客户端接收消息的function
let receiveCall = null
// 服务
let server = null
// 数据接收
function returnMsg(e){
receiveCall(e.data)
}
// 数据发送到服务端
function websendMsg(msg){
//发送的内容必须是JSON格式的
server.send(JSON.stringify(msg))
}
// 初始化 webscoket
function initWebscoket(){
// 声明服务
server = new WebScoket(WsUrl)
// 绑定相关的事件处理函数
server.onopen = function (e) {
console.log('连接成功',e)
}
server.onerror = function (e) {
console.log('连接出错',e)
}
server.onClose = function (e) {
console.log('连接关闭',e)
}
server.onmessage = function (e){
console.log('接收消息',e)
// 执行返回给客户端的function
returnMsg(e)
}
}
initWebscoket()
// 调用
function ActualCall (agentData, callback) {
// agentData 客户端发送到服务器的数据
// callback 客户端处理服务器发送数据的function
receiveCall = callback
if(server.readyState === server.OPEN){
// ws开启状态 直接发送数据
websendMsg(agentData)
} else if (server.readyState === server.CONNECTING){
// 正在开启状态 等待1秒 重新调用
setTimeout(()=>{
ActualCall(agentData,callback)
},1000)
} else {
// 若没有开启 等待1秒 重新调用
setTimeout(()=>{
ActualCall(agentData,callback)
},1000)
}
}
export { ActualCall }
main.js 文件中
import * as scoketAPI from './server/index.js'
// 绑定到原型上
Vue.prototype.scoketApI = scoketAPI
某个组件中调用
this.scoketAPI.ActualCall(
'客户端需要发送给服务端的数据','客户端接收处理服务端数据的function')
// 第二个参数是个function