1. tp5安装 workerman

参考 https://www.yisu.com/zixun/603043.html

composer require topthink/think-worker
 
composer报错 设置低版本
 
	composer require topthink/think-worker=1.*
 
window下还需要
composer require workerman/workerman-for-win

安装完成之后
在这里插入图片描述

2.创建workerman的服务

a) 跟application同目录下,即根目录下 创建 server.php, 内容如下:

<?php

define('APP_PATH', __DIR__ . '/application/');

define('BIND_MODULE','push/Worker');

// 加载框架引导文件

require __DIR__ . '/thinkphp/start.php';

// 此文件为 workerman 运行文件

b) 创建 workerman 的控制器

app/push/Worker 目录

<?php
namespace app\push\controller; 
use think\worker\Server; 
use Workerman\Lib\Timer;

class Worker extends Server{  

    protected $socket = 'websocket://127.0.0.1:2346'; 
    /**
     * 收到信息
     * @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)
    {
 
    }
}

c) 启动workerman服务

在cmd下运行 php server.php
在这里插入图片描述

前端 连接

a) 浏览器测试连接

打开chrome浏览器,按F12打开调试控制台,在Console一栏输入(或者把下面代码放入到html页面用js运行)

// 假设服务端ip为127.0.0.1
ws = new WebSocket("ws://127.0.0.1:2346");
ws.onopen = function() {
    alert("连接成功");
    ws.send('tom');
    alert("给服务端发送一个字符串:tom");
};
ws.onmessage = function(e) {
    alert("收到服务端的消息:" + e.data);
};

b) h5

<!DOCTYPE html>
<html xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <title>ThinkCMF WebSocket Demo</title>
 
    <script src="__STATIC__/js/jquery-2.0.3.min.js"></script>
</head>
<body>
 
<div id="app">
    软件模拟获取最新消息:
    <button class="get-msg">请求</button>
 
    <div class="return-msg">
        
    </div>
</div>
 
<script>
 
$(document).on('click','.get-msg',function(){
    ws = new WebSocket("ws://127.0.0.1:2346");
    
    //组织参数
    var param = new Array();
    param.push('software_send_msg');
    param.push('wydyhdzh');
 
    ws.onopen = function() {
        ws.send(param.join('|'));//向服务器返送信息
    };
 
    ws.onmessage = function(e) {//服务器返回信息
        var data = JSON.parse(e.data);
    
        if(data.result == 'success'){
            var list = JSON.parse(data.data);
            $('.return-msg').html(data.data);
        }
    };
})
    
</script>
</body>
</html>

c) vue

参考
https://blog.csdn.net/ych1274816963/article/details/121822432
https://blog.csdn.net/ZhouLoverBrother/article/details/111147571

<template>
	<view class="container">
		<!--  需求:通过websocket实时获取数据,赋值到输入框 ,如果websocket链接失败则弹窗警告-->
		  <view class="content-left">
			     <!-- 扫描条码 -->
				 <view class="textFontSize scan-container">
						<view class="mr-2 color-red font-w-b" style="font-size: 35rpx;">扫描条码:</view>
						<view class="scanBox flex-1 mr-1">
								<input class="flex-1 pl-2" type="text" confirm-type="search" placeholder="请扫描载具条码" v-model="scanCode"/>
						</view>
						<view class="scan-btn">
							<text class="iconfont icon-dagou"></text>
							<text class="ml-2">扫描提交</text>
						</view>
				 </view>
				 
		  </view>  
		   <!-- websocket连接失败弹窗 -->
		   <u-mask :show="socketShow" >
		   		<view class="warp">
		   			<u-tag :text="webtext" mode="dark" class="warp-tag" type="error"/>
		   		</view>
		   	</u-mask>
	</view>
</template>
<script>

import { websocetObj } from '@/utils/websocet/websocet.js';

export default {
		data() {
			return {
				     socketShow:false,
					webtext:'',
					
			  }
		},
		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);
			}   
		},
		mounted() {
		},
		onLoad() {
	    // 在onload的时候调用,创建webscoet连接对象,参数分别为:url、获取后端返回数据、监听websocket的链接失败返回的报错、监听链接状态,返回布尔值
			websocetObj.sokcet('ws://192.168.xxxx',this.getWebsocetData,this.getWebsocetError,this.onErrorSucceed)
		
    },
    //离开页面销毁websocket
		beforeDestroy() {
			websocetObj.stop();
	   },
	}
</script>

websocet.js 封装的 js

let isSocketClose=false;    // 是否关闭socket
let reconnectCount=5;    // 重连次数
let heartbeatInterval="";   // 心跳定时器
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
 };

效果
前台
在这里插入图片描述

后台

在这里插入图片描述

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐