webman+vue自定义websocket进程后端主动推送消息给客户端

xiaozhige

一、后端代码

需求:后端定时推送数据给客户端。

1、webman 新建 process/Websocket.php自定义监听进程文件

<?php
namespace process;

use Workerman\Connection\TcpConnection;
use Workerman\Timer;

/***
 * 开启一个websocket
 * Class Export
 * @package process
 */
class Websocket
{
    public function onConnect(TcpConnection $connection){}

    public function onWebSocketConnect(TcpConnection $connection, $http_buffer){}

    public function onMessage(TcpConnection $connection, $data)
    {
        $data = json_decode($data, true);

        Timer::add(1, function() use ($data){
            // >>>>>>>>>>>>>>>>>>>>>>>
            // 处理代码业务
            // >>>>>>>>>>>>>>>>>>>>>>>

            // 发送数据  $return_ret 推送的数据
            $connection->send(json_encode($return_ret));
        });
    }

    public function onClose(TcpConnection $connection)
    {
        // 关闭websocket
        $connection->close();
    }
}

2、webman 在 config/process.php中添加如下配置

return [
    // 文件更新检测
    'monitor' => [
        'handler'     => process\FileMonitor::class,
        'reloadable'  => false,
        'constructor' => [
            // 监控这些目录
            'monitor_dir' => [
                app_path(),
                config_path(),
                base_path() . '/process',
                base_path() . '/support',
                base_path() . '/resource',
                base_path() . '/.env',
            ],
            // 监控这些后缀的文件
            'monitor_extensions' => [
                'php', 'html', 'htm', 'env'
            ]
        ]
    ],
    'Websocket'  => [
        'handler'  => process\Websocket::class,
        'listen'  => 'websocket://0.0.0.0:2233',
        'count'   => 1,
    ],
];

二、vue客户端配置

需求:想要在vue单页面应用全局使用 websocket,所以封装了一个websocket.js文件,以便全局引入调用

1、websocket.js文件

var websock = null;

var global_callback = null;
var serverPort = "2233"; // webSocket连接端口
var wsuri = "ws://127.0.0.1:" + serverPort;

function createWebSocket(callback) {

  if (websock == null || typeof websock !== WebSocket) {
    initWebSocket(callback);
  }
}

function initWebSocket(callback) {
  global_callback = callback;
  // 初始化websocket
  websock = new WebSocket(wsuri);
  websock.onmessage = function (e) {
    websocketonmessage(e);
  };
  websock.onclose = function (e) {
    websocketclose(e);
  };
  websock.onopen = function () {
    websocketOpen();
  };

  // 连接发生错误的回调方法
  websock.onerror = function () {
    console.log("WebSocket连接发生错误");
    //createWebSocket();啊,发现这样写会创建多个连接,加延时也不行
  };
}

// 实际调用的方法
function sendSock(agentData ) {

  if (websock.readyState === websock.OPEN) {
    // 若是ws开启状态
    websocketsend(agentData);
  } else if (websock.readyState === websock.CONNECTING) {
    // 若是 正在开启状态,则等待1s后重新调用
    setTimeout(function () {
      sendSock(agentData);
    }, 1000);
  } else {
    // 若未开启 ,则等待1s后重新调用
    setTimeout(function () {
      sendSock(agentData);
    }, 1000);
  }
}

function closeSock() {
  websock.close();
}

// 数据接收
function websocketonmessage(msg) {
  // console.log("收到数据:"+JSON.parse(e.data));
  // console.log("收到数据:"+msg);

  // global_callback(JSON.parse(msg.data));

  // 收到信息为Blob类型时
  let result = null;
  // debugger
  if (msg.data instanceof Blob) {
    const reader = new FileReader();
    reader.readAsText(msg.data, "UTF-8");
    reader.onload = (e) => {
      result = JSON.parse(reader.result);
      //console.log("websocket收到", result);
      global_callback(result);
    };
  } else {
    result = JSON.parse(msg.data);
    //console.log("websocket收到", result);
    global_callback(result);
  }
}

// 数据发送
function websocketsend(agentData) {
  console.log("发送数据:" + agentData);
  websock.send(agentData);
}

// 关闭
function websocketclose(e) {
  console.log("connection closed (" + e.code + ")");
}

function websocketOpen(e) {
  console.log("连接打开");
}

export { sendSock, createWebSocket, closeSock };

2、在app.vue创建websocket链接

<template>
  <div id="app">
    <router-view/>
  </div>
</template>
import { createWebSocket } from "@/libs/websocket";
export default {
  name: 'app',
  created () {
    // 链接websocket
    createWebSocket();
  }
}
</script>

3、在其他单页面接受服务端数据

<template>
  <div></div>
</template>
import { createWebSocket, sendSock } from "@/libs/websocket";
export default {
  name: 'app',
  created () {
    // 链接websocket
    createWebSocket();
  },
  mounted() {
    // 发送websocket信息给服务器
    let sendData = {
      type: 'task',
      uid: this.info.admin.admin_id
    };
    sendSock(JSON.stringify(sendData));
    createWebSocket(this.socketGlobalCallback);
  },
  methods: {
    // 接受服务端数据
    socketGlobalCallback(msg){
      console.log('接受服务端数据', msg)
      // 赋值

    },
  }
}
</script>

三、客户端退出登录时关闭websocket

在注销登录组件中引入文件

import { closeSock } from "@/libs/websocket";

在注销事件中调用关闭websocket的方法closeSock

closeSock()
251 0 2
0个评论

xiaozhige

202
积分
0
获赞数
0
粉丝数
2021-03-27 加入
🔝