TP6 中使用 gateway-worker
安装:
composer require topthink/think-worker
更新镜像
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
配置:在config/下面有三个文件,修改端口
gateway_worker.php
worker.php
worker_server.php
//BusinsessWorker配置
'businessWorker' => [
'name' => 'BusinessWorker',
'count' => 1,
'eventHandler' => '\app\http\Events', //业务代码地址
],
启动:php think worker:gateway 关闭终端停止运行
推荐启动:php think worker:gateway -d 关闭终端依然运行
停止:php think worker:gateway stop
## wss 配置
* apache 配置: 开放一个端口,并在宝塔网站设置配置文件中加入以下代码。
<VirtualHost *:443>
SSLProxyEngine on
ProxyRequests Off
ProxyPass /wss ws://127.0.0.1:端口
ProxyPassReverse /wss wss://127.0.0.1:端口
* nginx 配置:开放一个端口,并在宝塔网站设置配置文件加入以下代码。
location /wss {
proxy_pass http://127.0.0.1:端口;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
rewrite /wss/(.*) /$1 break;
proxy_redirect off;
}
## 本地访问wss: ws://www.xxx.com/wss 或者 ws://ip:端口
## 前端访问wss: wss://www.xxx.com/wss
后端业务代码:
<?php
// 业务代码在 app/http/Events.php
namespace app\http;
use GatewayWorker\Lib\Gateway;
use Workerman\Worker;
use think\worker\Application;
/**
* Worker 命令行服务类
*/
class Events
{
/**
* onWorkerStart 事件回调
* 当businessWorker进程启动时触发。每个进程生命周期内都只会触发一次
*
* @access public
* @param \Workerman\Worker $businessWorker
* @return void
*/
public static function onWorkerStart(Worker $businessWorker)
{
$app = new Application;
$app->initialize();
}
/**
* onConnect 事件回调
* 当客户端连接上gateway进程时(TCP三次握手完毕时)触发
*
* @access public
* @param int $client_id
* @return void
*/
public static function onConnect($client_id)
{
//Gateway::sendToCurrentClient("Your client_id is $client_id");
}
/**
* onWebSocketConnect 事件回调
* 当客户端连接上gateway完成websocket握手时触发
*
* @param integer $client_id 断开连接的客户端client_id
* @param mixed $data
* @return void
*/
public static function onWebSocketConnect($client_id, $data)
{
//var_export($data);
}
/**
* onMessage 事件回调
* 当客户端发来数据(Gateway进程收到数据)后触发
*
* @access public
* @param int $client_id
* @param mixed $data
* @return void
*/
public static function onMessage($client_id, $data)
{
$arr = json_decode($data);
if($arr->type == "bind"){ //绑定客户端
Gateway::bindUid($client_id, $arr->id);
}else{
//一对一聊天
if($arr->mode=="single"){
Gateway::sendToUid($arr->receive_id, $data);
}
//群聊天
if($arr->mode=="group"){
$group_user_ids = [1,2,3]; //模拟群用户ID集合
foreach($group_user_ids as $key=>$value){
if($value != $arr->id){
Gateway::sendToUid($value, $data);
}
}
}
}
}
/**
* onClose 事件回调 当用户断开连接时触发的方法
*
* @param integer $client_id 断开连接的客户端client_id
* @return void
*/
public static function onClose($client_id)
{
GateWay::sendToAll(json_encode(['type'=>'close']));
}
/**
* onWorkerStop 事件回调
* 当businessWorker进程退出时触发。每个进程生命周期内都只会触发一次。
*
* @param \Workerman\Worker $businessWorker
* @return void
*/
public static function onWorkerStop(Worker $businessWorker)
{
echo "WorkerStop\n";
}
}
前端连接:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<input type="text" value="" id="send"> <input type="button" onclick="send()" value="发送"/>
<textarea name="" id="content" cols="30" rows="10"></textarea>
<script>
var ws = new WebSocket("ws://ip:端口"); //本地访问时
var ws = new WebSocket("wss://域名/wss"); //服务器上访问
ws.onopen = function(e){
console.log("连接成功")
let msg = {type:'bind', id:122}
ws.send(JSON.stringify(msg)) //绑定聊天对象
}
//接收到消息
ws.onmessage = function(e){
console.log(e)
document.getElementById("content").innerHTML = e
//发送心跳
setInterval(res=>{
ws.send(JSON.stringify({type:'ping'}))
console.log("发送心跳...")
},10000)
}
ws.onclose = function(e){
console.log("连接关闭",e)
}
function send(){
var txt = document.getElementById("send").value
let param = {type:'chat', receive_id:2, content:txt}
console.log(param);
ws.send(JSON.stringify(param))
}
</script>
</body>
</html>