tp6 workerman + vue websocket 链接

首先通过 composer 安装 workerman 

根项目下安装

composer require topthink/think-worker

安装的文件地址

 配置文件多出的 worker.php 和 worker_server.php

方法1 

worker.php文件

<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <[email protected]>
// +----------------------------------------------------------------------

// +----------------------------------------------------------------------
// | Workerman设置 仅对 php think worker 指令有效
// +----------------------------------------------------------------------
return [
    // 扩展自身需要的配置
    'host'                  => '0.0.0.0', // 监听地址,0.0.0.0外网内网都可以访问,也可以指定
    'port'                  => 9527, // 监听端口
    'root'                  => '', // WEB 根目录 默认会定位public目录
    'app_path'              => '', // 应用目录 守护进程模式必须设置(绝对路径)
    'file_monitor'          => false, // 是否开启PHP文件更改监控(调试模式下自动开启)
    'file_monitor_interval' => 2, // 文件监控检测时间间隔(秒)
    'file_monitor_path'     => [], // 文件监控目录 默认监控application和config目录

    // 支持workerman的所有配置参数
    'name'                  => 'thinkphp',
    'count'                 => 4,
    'daemonize'             => false,
    'pidFile'               => '',
];

worker_server.php文件

<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <[email protected]>
// +----------------------------------------------------------------------

// +----------------------------------------------------------------------
// | Workerman设置 仅对 php think worker:server 指令有效
// +----------------------------------------------------------------------
return [
    // 扩展自身需要的配置
    'protocol'       => 'websocket', // 协议 支持 tcp udp unix http websocket text
    'host'           => '0.0.0.0', // 监听地址,0.0.0.0外网内网都可以访问,也可以指定
    'port'           => 9527, // 监听端口
    'socket'         => '', // 完整监听地址
    'context'        => [], // socket 上下文选项
    'worker_class'   => '', // 自定义Workerman服务类名 支持数组定义多个服务

    // 支持workerman的所有配置参数
    'name'           => 'thinkphp',
    'count'          => 4,
    'daemonize'      => false,
    'pidFile'        => '',

    // 支持事件回调
    // onWorkerStart
    'onWorkerStart'  => function ($worker) {

    },
    // onWorkerReload
    'onWorkerReload' => function ($worker) {

    },
    // onConnect
    'onConnect'      => function ($connection) {

    },
    // onMessage
    'onMessage'      => function ($connection, $data) {
        $connection->send('receive success 123');
    },
    // onClose
    'onClose'        => function ($connection) {

    },
    // onError
    'onError'        => function ($connection, $code, $msg) {
        echo "error [ $code ] $msg\n";
    },
];

方法2推荐

上面的两个文件可以不用理,我们自定一个Worker类

worker_server.php文件 worker_class地方加上Worker.php位置

'worker_class'   => 'Worker.php位置',位置错了会报错找不到文件

<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <[email protected]>
// +----------------------------------------------------------------------

// +----------------------------------------------------------------------
// | Workerman设置 仅对 php think worker:server 指令有效
// +----------------------------------------------------------------------
return [
    // 扩展自身需要的配置
    'protocol'       => 'websocket', // 协议 支持 tcp udp unix http websocket text
    'host'           => '0.0.0.0', // 监听地址
    'port'           => 9527, // 监听端口
    'socket'         => '', // 完整监听地址
    'context'        => [], // socket 上下文选项
    'worker_class'   => 'app\controller\Index\Worker', // 自定义Workerman服务类名 支持数组定义多个服务

    // 支持workerman的所有配置参数
    'name'           => 'thinkphp',
    'count'          => 4,
    'daemonize'      => false,
    'pidFile'        => '',

    // 支持事件回调
    // onWorkerStart
    'onWorkerStart'  => function ($worker) {

    },
    // onWorkerReload
    'onWorkerReload' => function ($worker) {

    },
    // onConnect
    'onConnect'      => function ($connection) {

    },
    // onMessage
    'onMessage'      => function ($connection, $data) {
        $connection->send('receive success 123');
    },
    // onClose
    'onClose'        => function ($connection) {

    },
    // onError
    'onError'        => function ($connection, $code, $msg) {
        echo "error [ $code ] $msg\n";
    },
];

创建好之后

Worker.php代码

<?php

namespace app\controller\Index;

use think\worker\Server;
use Workerman\Lib\Timer;

class Worker extends Server{

    protected $socket = 'websocket://0.0.0.0:9527';
    /**
     * 收到信息
     * @param $connection
     * @param $data
     */
    public function onMessage($connection, $data)
    {
        echo '后台收到前台的信息';
        echo $data;
        $connection->send('我收到你的信息了,后台收到前台的信息了');
    }
    /**
     * 当连接建立时触发的回调函数
     * @param $connection
     */
    public function onConnect($connection)
    {

    }
    /**
     * 当连接断开时触发的回调函数
     * @param $connection
     */
    public function onClose($connection)
    {

    }    /**
 * 当客户端的连接上发生错误时触发
 * @param $connection
 * @param $code
 * @param $msg
 */
    public function onError($connection, $code, $msg)
    {
        echo "error $code $msg\n";
    }
    /**
     * 每个进程启动
     * @param $worker
     */
    public function onWorkerStart($worker)
    {

    }
}

试着启动下服务

php think worker:server

 如下图,表示启动正常

 如果出现错误,先查看下端口是否已放行

如果是php环境是第一次安装,有些对应的禁用函数需要删除,启动时会提示哪些函数被禁用了

vue,uniapp也是同理 

websocet.js封装好了类

let isSocketClose = false; // 是否关闭socket
let reconnectCount = 5; // 重连次数
let heartbeatInterval = "50"; // 心跳定时器
let socketTask = null; // websocket对象

let againTimer = null; //断线重连定时器


let url = null;
let onReFn = null;
let onSucFn = null;
let onErrFn = null;

/**
 * sockeUrl:websocet的地址
 * onReceive:消息监听的回调
 * onErrorEvent:抛出错误的回调,且弹窗连接失败的提示框
 * onErrorSucceed:抛出成功回调,主要用于隐藏连接失败的提示框
 * */
const sokcet = (sockeUrl, onReceive, onErrorEvent, onErrorSucceed) => {
	url = sockeUrl;
	onReFn = onReceive;
	onErrFn = onErrorEvent;
	onSucFn = onErrorSucceed;
	isSocketClose = false;
	//判断是否有websocet对象,有的话清空
	if (socketTask) {
		socketTask.close();
		socketTask = null;
		clearInterval(heartbeatInterval);
	}

	//WebSocket的地址
	// 【非常重要】必须确保你的服务器是成功的,如果是手机测试千万别使用ws://127.0.0.1:9099【特别容易犯的错误】
	let url = sockeUrl
	// 连接
	socketTask = uni.connectSocket({
		url: url,
		success(data) {
			console.log("websocket连接成功");
			clearInterval(againTimer) //断线重连定时器
		},
		fail: (err) => {
			console.log("报错", err);
		}
	});

	// 连接打开
	socketTask.onOpen((res) => {
		console.log('WebSocket打开');
		clearInterval(againTimer) //断线重连定时器
		onErrorSucceed({
			isShow: false
		}) // 用于提示框的隐藏
		heartbeatInterval && clearInterval(heartbeatInterval);
		// 10秒发送一次心跳
		heartbeatInterval = setInterval(() => {
			sendMsg('心跳ing')
		}, 1000 * 5)
	})
	// 监听连接失败
	socketTask.onError((err) => {
		console.log('WebSocket连接打开失败,请检查', err);
		//停止发送心跳
		clearInterval(heartbeatInterval)
		//如果不是人为关闭的话,进行重连
		if (!isSocketClose) {
			reconnect(url, onErrorEvent)
		}
	})

	// // 监听连接关闭 -
	socketTask.onClose((e) => {
		console.log('WebSocket连接关闭!');
		clearInterval(heartbeatInterval)
		if (!isSocketClose) {
			reconnect(url, onErrorEvent)
		}
	})

	// 监听收到信息
	socketTask.onMessage((res) => {
		uni.hideLoading()
		console.log(res, 'res监听收到信息')
		let serverData = res.data
		//与后端规定好返回值分别代表什么,写业务逻辑
		serverData && onReceive(serverData);
	});


}

const reconnect = (url, onErrorEvent) => {
	console.log('进入断线重连', isSocketClose);
	clearInterval(againTimer) //断线重连定时器
	clearInterval(heartbeatInterval);
	socketTask && socketTask.close(); // 确保已经关闭后再重新打开
	socketTask = null;
	onErrorEvent({
		isShow: true,
		messge: '扫描头服务正在连接...'
	})
	// 连接  重新调用创建websocet方法
	againTimer = setInterval(() => {
		sokcet(url, onReFn, onErrFn, onSucFn)
		console.log('在重新连接中...');
	}, 1000 * 5)


}

const sendMsg = (msg) => { //向后端发送命令
	msg = JSON.stringify(msg)
	try {
		//通过 WebSocket 连接发送数据
		socketTask.send({
			data: msg
		});
	} catch (e) {
		if (isSocketClose) {
			return
		} else {
			reconnect(url, onErrFn)
		}

	}
}
// 关闭websocket【必须在实例销毁之前关闭,否则会是underfined错误】beforeDestroy() {websocetObj.stop();}

const stop = () => {
	isSocketClose = true
	clearInterval(heartbeatInterval);
	clearInterval(againTimer) //断线重连定时器
	socketTask.close(); // 确保已经关闭后再重新打开
	socketTask = null;
}





export const websocetObj = {
	sokcet,
	stop,
	sendMsg
};

 需要引用的页面

<script>
	import {
		websocetObj
	} from '@/http/websocet.js';
	export default {
		data() {
			return {
				
			}
		},

		onLoad() {
			// 在onload的时候调用,创建webscoet连接对象,参数分别为:url、获取后端返回数据、监听websocket的链接失败返回的报错、监听链接状态,返回布尔值
			websocetObj.sokcet('ws://服务器地址:端口/websocket', this.getWebsocetData, this.getWebsocetError, this.onErrorSucceed)
		},
		//离开页面销毁websocket
		beforeDestroy() {
			websocetObj.stop();
		},
		methods: {
			//websocet函数回调:返回监听的数据
			getWebsocetData(val) {
				// val = String.fromCharCode.apply(null, new Uint8Array(val)).trim()  //如果后端返回数据格式是其他的,可能需要转换一下,比如这个,应该是转Unicode编码
				console.log(val, '函数回调');
				// this.scanCode = val;
			},
			//websocet函数抛错: 返回错误信息 用于用户提示
			getWebsocetError(err) {
				this.socketShow = err.isShow;
				this.webtext = err.messge;
				console.log('websocet函数抛错', this.socketShow);
			},
			//websocet函数成功进入: 监听连接状态,在失败的时候弹窗提示,具体需求看自身情况
			onErrorSucceed(val) {
				this.socketShow = val.isShow;
				console.log('websocet函数成功进入', this.socketShow);
			}
		}
	}
</script>

 结果

前台

 后台

需要注意的是,如果使用wss协议的

如果是微信小程序,必须添加合法域名

vue 

地址一定要,wss://域名:端口/websocket

服务器

1、 安装 SSL 证书

您需要在服务器上安装有效的 SSL 证书,以启用 HTTPS 协议。如果您已经安装了 SSL 证书,请确保证书配置正确,并且证书链完整。如果您没有安装 SSL 证书,可以考虑购买或使用免费的证书,例如 Let's Encrypt。

这个配置还是比较麻烦,要还修改一些环境配置,具体就不写了,需要可以私聊....记得要清理游览器或者小程序缓存

不然会出现下面的错误,链接到了,可是加密文件不对

微信小程序 也可以不用wss协议

这样可以避免 SSL 证书验证,但会降低通信安全性。

本人踩了很多坑,还有啥问题,可以提出来

猜你喜欢

转载自blog.csdn.net/weixin_43453621/article/details/130347118