環境:基於composer引入包和thinkphp6+https+workerman.
1.composer引入gatewayworker 使用phpstorm更方便(在composer.json中require中添加這些 phpstorm會自動引入) 或者使用命令行 composer require XXX
"workerman/workerman": "^4.0", "workerman/gateway-worker": "^3.0", "workerman/gatewayclient": "^3.0",
0.編寫workerman啟動文件 workerman單獨部署的 與你的項目無關 public/workerman.php(這個用來測試workman啟動的-------------------)
<?php // +---------------------------------------------------------------------- // | ThinkPHP [ WE CAN DO IT JUST THINK ] // +---------------------------------------------------------------------- // | Copyright (c) 2006-2019 http://thinkphp.cn All rights reserved. // +---------------------------------------------------------------------- // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) // +---------------------------------------------------------------------- // | Author: liu21st <liu21st@gmail.com> // +---------------------------------------------------------------------- // [ wokerman啟動文件 和整個項目無關聯] namespace think; use Workerman\Worker; require_once __DIR__ . '/../vendor/workerman/workerman/Autoloader.php'; // 創建一個Worker監聽2345端口,使用http協議通訊 $http_worker = new Worker("http://0.0.0.0:2345"); // 啟動4個進程對外提供服務 $http_worker->count = 4; // 接收到瀏覽器發送的數據時回復hello world給瀏覽器 $http_worker->onMessage = function($connection, $data) { // 向瀏覽器發送hello world // $connection->send('hello world'); }; // 運行worker Worker::runAll();
2.利用命令創建workerman php think make:command workerman 並編寫文件app/command/Workerman.php
<?php //declare (strict_types=1); namespace app\command; use GatewayWorker\BusinessWorker; use GatewayWorker\Gateway; use GatewayWorker\Register; use think\console\Command; use think\console\Input; use think\console\input\Argument; use think\console\input\Option; use think\console\Output; use Workerman\Worker; require_once __DIR__ . '/../../vendor/workerman/workerman/Autoloader.php'; class Workerman extends Command { protected function configure() { // 指令配置 $this->setName('workerman') ->setDescription('the workerman command'); } protected function execute(Input $input, Output $output) { $this->startGateWay(); $this->startBusinessWorker(); $this->startRegister(); Worker::runAll(); } private function startBusinessWorker() { $worker = new BusinessWorker(); $worker->name = 'BusniessWorker'; $worker->count = 1; $worker->registerAddress = "127.0.0.1:1236"; $worker->eventHandler = \app\workerman\Events::class; } private function startGateWay() { $gateway = new Gateway("websocket://127.0.0.1:2346"); $gateway->name = 'Gateway'; $gateway->count = 1; $gateway->lanIp = '127.0.0.1'; $gateway->startPort = 2300; $gateway->pingInterval = 30; $gateway->pingNotResponseLimit = 0; $gateway->pingData = '{"type":"heart"}'; $gateway->registerAddress = "127.0.0.1:1236"; } private function startRegister() { new Register('text://127.0.0.1:1236'); } }
3.定義workerman監聽調用方法 heart心跳檢測
public function workerman_message($admin_id = '',$content=''){ Gateway::$registerAddress = '0.0.0.0:1236'; // 向任意uid的網站頁面發送數據 $uid = $admin_id; $admin = SystemAdmin::find($admin_id); $message = new \stdClass(); $message->type='send'; if($uid){ $message->from=$admin_id??''; $message->from_name=$admin['username']??'后台消息'; $message->from_avatar=$admin['head_img']??'https://www.huixx.cn/upload/20200828/e68c50db7b27c784b13a13b87c8ffc71.png'; $message->content=$content; Gateway::sendToUid($uid, json_encode($message,JSON_UNESCAPED_UNICODE)); }else{ $message->from_name='后台提醒'; $message->from_avatar='https://www.huixx.cn/upload/20200828/e68c50db7b27c784b13a13b87c8ffc71.png'; $message->content=$content; Gateway::sendToAll(json_encode($message,JSON_UNESCAPED_UNICODE)); } }
4.前端開啟websocket監聽 加載html提示框
/** * 與GatewayWorker建立websocket連接,域名和端口改為你實際的域名端口, * 其中端口為Gateway端口,即start_gateway.php指定的端口。 * start_gateway.php 中需要指定websocket協議,像這樣 * $gateway = new Gateway(websocket://0.0.0.0:7272); */ Notification.requestPermission(); let protocol = location.protocol === 'https:' ? 'wss://test.huixx.cn/wss/' : 'ws://0.0.0.0:2346'; ws = new WebSocket(protocol); console.log('websocket啟動') // 服務端主動推送消息時會觸發這里的onmessage ws.onmessage = function (e) { // json數據轉換成js對象 var data = eval("(" + e.data + ")"); var type = data.type ? data.type : ""; switch (type) { case 0: break; case "connect": console.log('連婕socket成功!'); /*進行id綁定*/ var url = '/workerman/bind'; var data_post = { client_id: data.id, }; $.post(url, data_post, function (re) { var r = /^[0-9]*$/; if (r.test(re)) { console.log('綁定uid:' + re + "成功"); } }, 'json'); //查詢未接收消息數 並且放置 break; case "heart": console.log('心跳檢測正常'); break; /*接受到消息的處理*/ case "send": //更新在線聊天按鈕 console.log(data); layer.msg(data.content) var domain = 'https://' + document.domain; var icon = ''; if (data.from_avatar.indexOf('https') != -1) { icon = data.from_avatar; } else { icon = domain + data.from_avatar; } var notification = new Notification(data.from_name, { body: data.content, icon: data.from_avatar }); notification.onclick = function () { window.focus(); notification.close(); } break; default: console.log(data) } };
其他,因為配置了https 所以要wss然后呢要在nginx中做相關配置 如果是http則無需配置 具體參考文檔:http://doc.workerman.net/faq/secure-websocket-server.html
location /wss { proxy_pass http://127.0.0.1:2346; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; }
注意上述代碼關系到的端口均要在雲服務器開通 在雲上開通。