下载websocket
composer require topthink/think-worker
创建websocket类
在项目的控制器中,新建一个websocket.php文件,里面写上:
<?php
namespace app\shop\controller;
use think\worker\Server;
use Workerman\Lib\Timer;
define('HEARTBEAT_TIME', 20);// 心跳间隔55秒
class Worker extends Server{
protected $socket = 'websocket://0.0.0.0:2345';
/**
* 收到信息
* @param $connection
* @param $data
*/
public function onMessage($connection, $data){
// echo '后台收到前台的信息';
// echo $data;
if($data === 'ping'){
$connection->send('pong');
}else{
$connection->send('你给我发送了'.$data.','.'我返回给你一坨狗屎');
}
}
/**
* 当连接建立时触发的回调函数
* @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) {
}
}
我是在宝塔中创建,如果2345端口没开,可以在宝塔中开启下,也可以在config\worker_server.php下修改端口号与socket完整监听地址
在config\worker_server.php引入刚刚创建的websocket类
配置完成之后在启动下socket:
php think worker:server
这样就配置完成了。
前端连接websocket
我是用uniapp做了一个demo,其中包含断开重连,心跳机制:
新建一个websocket.js文件,写入
class webSocketClass {
constructor(url = '你的socket地址', time = 600) {
this.url = url
this.data = null
this.isCreate = false // WebSocket 是否创建成功
this.isConnect = false // 是否已经连接
this.isInitiative = false // 是否主动断开
this.timeoutNumber = time // 心跳检测间隔
this.heartbeatTimer = null // 心跳检测定时器
this.reconnectTimer = null // 断线重连定时器
this.socketExamples = null // websocket实例
this.againTime = 3 // 重连等待时间(单位秒)
}
// 初始化websocket连接
initSocket() {
const _this = this
this.socketExamples = uni.connectSocket({
url: _this.url,
header: {
'content-type': 'application/json'
},
success: (res) => {
_this.isCreate = true
console.log(res)
},
fail: (rej) => {
console.error(rej)
_this.isCreate = false
}
})
this.createSocket()
}
// 创建websocket连接
createSocket() {
if (this.isCreate) {
console.log('WebSocket 开始初始化')
// 监听 WebSocket 连接打开事件
try {
this.socketExamples.onOpen(() => {
console.log('WebSocket 连接成功')
this.isConnect = true
clearInterval(this.heartbeatTimer)
clearTimeout(this.reconnectTimer)
// 打开心跳检测
this.heartbeatCheck()
})
// 监听 WebSocket 接受到服务器的消息事件
this.socketExamples.onMessage((res) => {
console.log('收到消息')
uni.$emit('message', res)
})
// 监听 WebSocket 连接关闭事件
this.socketExamples.onClose(() => {
console.log('WebSocket 关闭了')
this.isConnect = false
this.reconnect()
})
// 监听 WebSocket 错误事件
this.socketExamples.onError((res) => {
console.log('WebSocket 出错了')
console.log(res)
this.isInitiative = false
})
} catch (error) {
console.warn(error)
}
} else {
console.warn('WebSocket 初始化失败!')
}
}
// 发送消息
sendMsg(value) {
const param = JSON.stringify(value)
return new Promise((resolve, reject) => {
this.socketExamples.send({
data: param,
success() {
console.log('消息发送成功')
resolve(true)
},
fail(error) {
console.log('消息发送失败')
reject(error)
}
})
})
}
// 开启心跳检测
heartbeatCheck() {
console.log('开启心跳')
this.data = { state: 1, method: 'heartbeat' }
this.heartbeatTimer = setInterval(() => {
this.sendMsg(this.data)
}, this.timeoutNumber * 1000)
}
// 重新连接
reconnect() {
// 停止发送心跳
clearTimeout(this.reconnectTimer)
clearInterval(this.heartbeatTimer)
// 如果不是人为关闭的话,进行重连
if (!this.isInitiative) {
this.reconnectTimer = setTimeout(() => {
this.initSocket()
}, this.againTime * 1000)
}
}
// 关闭 WebSocket 连接
closeSocket(reason = '关闭') {
const _this = this
this.socketExamples.close({
reason,
success() {
_this.data = null
_this.isCreate = false
_this.isConnect = false
_this.isInitiative = true
_this.socketExamples = null
clearInterval(_this.heartbeatTimer)
clearTimeout(_this.reconnectTimer)
console.log('关闭 WebSocket 成功')
},
fail() {
console.log('关闭 WebSocket 失败')
}
})
}
}
export default webSocketClass
然后在页面中使用:
<template>
<view class="container fs_middle">
<view class="flex around middle p_20 sizing">
<u--input placeholder="请输入内容" border="surround" v-model="keyword"></u--input>
<u-button type="primary" size="small" text="发送消息" color="#ffbf00" @click="sendMessage"></u-button>
</view>
<view class="mt_20 box_center p_20 sizing bc_white b_r_10">
<view class="blod fs_big">
<text>服务端返回消息:</text>
</view>
<view class="mt_20">
<text>{{ content }}</text>
</view>
</view>
</view>
</template>
<script>
import webSocketClass from '@/utils/websocker2.js'
export default{
data () {
return {
webSocketTask: null,
keyword: '',
content: ''
}
},
onLoad(){
// this.socket()
this.webSocketTask = new webSocketClass();
this.webSocketTask.initSocket();
uni.$on('message', this.getMessage);
},
onUnload () {
uni.$off('message', this.getMessage);
},
methods: {
// // 发送消息至服务端
sendMessage () {
this.webSocketTask.sendMsg(this.keyword);
},
getMessage(res) {
this.content = res.data;
}
},
}
</script>
<style lang="scss" scoped>
/deep/ .u-button{
width: 120rpx;
height: 76rpx;
margin-left: 20rpx;
}
</style>
这样就可以前端发送一条消息,后台接收到,就会返回前端一条消息。