首先现在根目录执行安装workerman
composer require workerman/workerman
composer install/update
创建自定义 artisan 命令来启动 workerman 服务
php artisan make:command WorkermanCommand
在 app/Console/Commands/ 目录下生成 WorkermanCommand.php 文件。
代码如下:
<?php namespace App\Console\Commands; use Illuminate\Console\Command; use Illuminate\Support\Facades\Cache; use Workerman\Lib\Timer; use Workerman\Worker; class WorkermanCommand extends Command { private $server; // -d 是否以debug方式运行 protected $signature = 'workerman {action} {-d?}'; protected $description = 'Start a Workerman server.'; public function __construct() { parent::__construct(); } /** * Execute the console command. * * @return mixed */ public function handle() { global $argv; $arg = $this->argument('action'); $argv[1] = $argv[2]; $argv[2] = isset($argv[3]) ? "-{$argv[3]}" : ''; switch ($arg) { case 'start': $this->start(); break; case 'stop': $this->stop(); break; case 'restart': $this->restart(); break; case 'reload': $this->reload(); break; } } private function start() { // 创建一个Worker监听8383端口,不使用任何应用层协议 $this->server = new Worker("websocket://0.0.0.0:8383"); // 启动1个进程对外提供服务,倘若要实现客户端与服务端交互,则必须设置为1 $this->server->count = 1; //处理客户端传来的消息 $this->server->onMessage = function ($connection, $data) { $connection->lastMessageTime = time(); $data = json_decode($data, true); if (!isset($connection->openid)) { //这里你可将用户的唯一标识绑定这个连接,我这里用的是openid .... $this->server->openidConnetcions[$connection->openid] = $connection; $connection->send("Accepts success"); } }; //启动worker进程,建立一个内部端口,方便内部系统推送数据 $this->server->onWorkerStart = function ($worker) { // 进程启动后设置一个每秒运行一次的定时器,心跳(长连接则需要) Timer::add(1, function()use($worker){ $time_now = time(); foreach($worker->connections as $connection) { // 有可能该connection还没收到过消息,则lastMessageTime设置为当前时间 if (empty($connection->lastMessageTime)) { $connection->lastMessageTime = $time_now; continue; } // 上次通讯时间间隔大于心跳间隔,则认为客户端已经下线,关闭连接, HEARTBEAT_TIME是心跳时间,是个常量 if ($time_now - $connection->lastMessageTime > HEARTBEAT_TIME) { $connection->close(); } } }); //建立内部连接, 后端内部可向此连接发送信息 $inner_text_worker = new Worker('text://0.0.0.0:5678'); $inner_text_worker->onMessage = function ($connection, $buffer) { $data = json_decode($buffer, true); $openid = $data['openid']; $ret = $this->sendMessageByOpenid($openid, $buffer); $connection->send($ret ? 'ok' : 'fail'); }; $inner_text_worker->listen(); }; $this->server->onClose = function ($connection) { echo "connection closed from ip {$connection->getRemoteIp()}\n"; if (isset($connection->openid)) { unset($this->server->openidConnetcions[$connection->openid]); echo "connection closed from ip {$connection->getRemoteIp()}\n"; } }; $this->server->onConnect = function ($connection) { echo "连接成功"; }; Worker::runAll(); } private function stop() { $this->server = new Worker('websocket://0.0.0.0:8383'); // 设置此实例收到reload信号后是否reload重启 $this->server->reloadable = false; $this->server->onWorkerStop = function($worker) { echo "Worker stop...\n"; }; // 运行worker Worker::runAll(); } private function restart() { $this->server = new Worker('websocket://0.0.0.0:8383'); // 设置此实例收到reload信号后是否reload重启 $this->server->reloadable = true; $this->server->onWorkerStart = function($worker) { echo "Worker restart...\n"; }; // 运行worker Worker::runAll(); } private function reload() { $this->server = new Worker('websocket://0.0.0.0:8383'); // 设置此实例收到reload信号后是否reload重启 $this->server->reloadable = false; $this->server->onWorkerStart = function($worker) { echo "Worker reload...\n"; }; // 运行worker Worker::runAll(); } //接受内部推送数据后向指定用户推送消息 private function sendMessageByOpenid($openid, $message) { if (isset($this->server->openidConnetcions[$openid])) { $connection = $this->server->openidConnetcions[$openid]; $connection->send($message); return true; } return false; } }
后端推送消息到前端的代码
// 建立socket连接到内部推送端口 $client = stream_socket_client('tcp://127.0.0.1:5678', $errno, $errmsg, 1); // 推送的数据,包含uid字段,表示是给这个uid推送 $data = array('uid'=>'uid1', 'percent'=>'88%'); // 发送数据,注意5678端口是Text协议的端口,Text协议需要在数据末尾加上换行符 fwrite($client, json_encode($data)."\n"); // 读取推送结果 echo fread($client, 8192);
最后可执行命令来启动workerman服务
php artisan workerman start d