tp6 workerman + vue websocket link

First install workerman via composer 

Install under the root project

composer require topthink/think-worker

Installed file address

 The extra worker.php and worker_server.php in the configuration file

method 1 

worker.php file

<?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 file

<?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";
    },
];

Method 2 Recommended

The above two files can be ignored, we customize a Worker class

worker_server.php file worker_class place plus Worker.php location

'worker_class' => 'Worker.php location', if the location is wrong, an error will be reported and the file cannot be found

<?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";
    },
];

After creating

Worker.php code

<?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)
    {

    }
}

Try to start the service

php think worker:server

 As shown in the figure below, it means that the startup is normal

 If an error occurs, first check whether the port has been released

If the php environment is installed for the first time, some corresponding disabled functions need to be deleted, and it will prompt which functions are disabled when starting

The same is true for vue and uniapp 

websocet.js encapsulates the class

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
};

 Pages that need to be cited

<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>

 result

front desk

 Backstage

It should be noted that if the wss protocol is used

If it is a WeChat applet, a legal domain name must be added

vue 

The address must be wss://domain name:port/websocket

server

1. Install an SSL certificate

You need to have a valid SSL certificate installed on the server to enable the HTTPS protocol. If you have installed an SSL certificate, make sure the certificate is configured correctly and the certificate chain is complete. If you don't have an SSL certificate installed, consider purchasing or using a free certificate such as Let's Encrypt.

This configuration is still quite troublesome. If you need to modify some environment configurations, I won’t write the details. You can chat privately if you need to. Remember to clear the browser or applet cache

Otherwise, the following error will appear, the link is here, but the encrypted file is wrong

WeChat applet can also use wss protocol

This avoids SSL certificate verification, but reduces communication security.

I stepped on a lot of pitfalls, if there are any questions, you can ask them

おすすめ

転載: blog.csdn.net/weixin_43453621/article/details/130347118