随手记
首页 分类 成员 关于

vue+websocket模拟即时通讯

发表于: 2020-10-09 00:00:00 by arvin

分类于:javascript

阅读:

什么是WebSocket?

WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。

WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

现在,很多网站为了实现推送技术,所用的技术都是 Ajax 轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。

HTML5 定义的 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。

WebSocket 事件

事件 事件处理程序 描述
open Socket.onopen 连接建立时触发
message Socket.onmessage 客户端接收服务端数据时触发
error Socket.onerror 通信发生错误时触发
close Socket.onclose 连接关闭时触发

WebSocket 方法

方法 描述
Socket.send() 使用连接发送数据
Socket.close() 关闭连接

示例

1.客户端搭建

客户端是由vue脚手架搭建,如果比较熟的小伙伴可直接跳到后面,首先打开命令行工具,全局安装vue-cli

npm install -g @vue/cli

然后创建一个新项目

vue create my-project
# OR
vue ui

按照自己的喜好点点点,构建完成后,找到页面/src/App.vue,覆盖以下代码

 <template>
   <div class="container">
     <button @click="openConnect" v-if="!isConnected">打开连接</button>
     <button @click="closeConnect" v-if="isConnected">关闭连接</button>
     <label for="input" v-if="isConnected">
       <input id="input" v-model="message"/>
       <button @click="sendMessage">发送信息</button>
     </label>
     <ul>
       <li v-for="(item,index) in messageList" :key="index">
         <span v-if="item.type===0" class="type1"> 欢迎登录</span>
         <span v-if="item.type===1" class="type2">:</span>
         <span v-if="item.type===2" class="type3">已退出</span>
       </li>
     </ul>
   </div>
 </template>
 
 <script>
 export default {
   data() {
     return {
       message: null,//当前输入消息
       messageList: [],//消息列表
       ws: null,//ws实例
       isConnected: false,//是否处于连接
     }
   },
   methods: {
     /**
      *@dec 打开连接
      */
     openConnect() {
       if ("WebSocket" in window) {//判定ws兼容
         const ws = new WebSocket("ws://localhost:8080");//地址为服务器接口地址
 
         ws.onopen = () => { // 连接成功时
           this.isConnected = true;
         };
 
         ws.onmessage = (evt) => { // 发送信息时
           this.messageList.push(JSON.parse(evt.data));
         };
 
         ws.onclose = () => { // 关闭连接时
           this.isConnected = false;
         };
 
         ws.onerror = (err) => {  // 连接错误时
           console.log('err',err)
           this.isConnected = false;
         }
 
         this.ws = ws;
       } else {
         alert("您的浏览器不支持 WebSocket!");
       }
     },
 
     /**
      *@dec 发送信息
      */
     sendMessage() {
       if (this.ws && this.message) {
         this.ws.send(this.message);
         this.message = "";
       }
     },
 
     /**
      *@dec 关闭连接
      */
     closeConnect() {
       if (this.ws) this.ws.close();
     }
   }
 }
 </script>
 
 <style>
 
 .type1 {
   color: #999;
 }
 
 .type2 {
 
 }
 
 .type3 {
   color: #999;
 }
 </style>

然后在命令行输入

  npm run serve

启动服务,具体内容可参考VUE-CLI

现在点击’打开连接’还是会报错,因为我们的后端服务还没开启,下面我们建立服务端

2.服务端

服务端是用express搭建,是一个基于 Node.js 平台,搭建方法很简单,假定你已经安装了Node.js,接下来进入命令行工具,为你的应用创建一个目录,然后进入此目录并将其作为当前工作目录。

mkdir myapp
cd myapp

然后通过命令,创建一个 package.json 文件

npm init -y

接下来在 myapp 目录下安装 Express 并将其保存到依赖列表中

npm install express --save

然后安装websocket

npm install ws --save

安装完成后,在根目录下新建server.js,并写入内容

const WebSocket = require('ws');
const server = new WebSocket.Server({port: 8080});//端口号不要和客户端端口号重复
console.log('服务启动成功')

let userList = [];// 用户列表,每个登录的用户都会存储在里面

let broadcast = mesObj => {// 消息广播,即用户列表里的每个用户都会收到消息
    userList.forEach(item => {
        item.send(JSON.stringify({// send只能发送字符串
            uid: mesObj.uid, //唯一id
            message: mesObj.message,//发送的信息
            type: mesObj.type//发送的类型,0是登录,1是发送消息时,2是退出时
        }));
    })
}

server.on('connection', function connection(ws) {//当有用户建立连接时

    ws.uid = [(new Date()).getTime(), Math.floor(Math.random() * 10000)].join('_');//由于没有连接数据库,创建随机数id
    userList.push(ws);//将用户存储到userList
console.log(ws.uid)
    broadcast({ //发送登录通知
        uid: ws.uid,
        message: '欢迎登录',
        type: 0
    })

    ws.on('message', message => { //当用户发消息时
        broadcast({ //转发给所有人
            uid: ws.uid,
            message,
            type: 1
        })
    })

    ws.on('close', () => {//当用户退出时
        broadcast({//转发给所有人
            uid: ws.uid,
            message: '已退出',
            type: 2
        })
    })
});

在命令行内,启动express服务

node server.js  

具体命令可参考Express中文网,最后可以打开多个客户端页面,互相发消息啦,当然这只是个简单的本地模拟,如果想要更加具体,可以添加mysql来管理具体用户,这在里就不多说啦