Laravel workerman 创建并实时聊天

384 阅读1分钟

Laravel workerman 创建并实时聊天 操作文档

1. 安装composer require workerman/workerman

2. 运行php artisan workerman start

3. 以daemon(守护进程)方式启动php artisan workerman start-d

4. php artisan workerman reload // 重新加载配置

5. php artisan workerman reload // 重启workerman

6. php artisan workerman stop // 停止workerman

7. workerman创建php artisan make:command 文件名

8. 修改文件protected $signature = '进程名 {action}';

9. workerman注册Kernel.php protected $commands = [文件类];
<?php

namespace App\Console\Commands;

use Illuminate\Auth\TokenGuard;
use Illuminate\Console\Command;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Log;
use Workerman\Worker;
use Workerman\Lib\Timer;
use Illuminate\Support\Facades\DB;
use Exception;
use Workerman\Protocols\Http\Request;

class Workerman extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'workerman {action}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Workerman Server';


    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        // global $worker;
        // $worker = new Worker('websocket://' . env('HOST', '127.0.0.1') . ':' . env('WEBSOCKET_PORT', '1234'));

        // global $argv; //$argv 在ArgvInput类中被定义了,就是$_SERVER['argv'];
        // $arg = $this->argument('action');
        // $argv[1] = $argv[2];
        // $argv[2] = isset($argv[3]) ? "-{$argv[3]}" : '';
        // Log::info($arg);
        // switch ($arg) {
        //     // case 'restart':
        //     //     $this->info('workerman server restarted');
        //     //     break;
        //     // case 'close':
        //     //     $this->info('workerman server stoped');
        //     //     break;
        //     //default:
        //     case 'start':
        //         $this->start($request);
        //         break;
        // }
        $this->start();
    }


    private function start()
    {
        //建立socket连接
        $http_worker = new Worker('websocket://127.0.0.1:2001');
        // 启动4个进程对外提供服务
        $http_worker->count = 1;
        //定义一个属性,用来存放用户的连接信息,$connection
        $http_worker->uidConnections = array();
        //socket事件类中的,链接属性,调用闭包函数
        $http_worker->onConnect = function ($connection) use ($http_worker) {
            // 设置连接的onMessage回调
            $connection->onMessage = function ($connection, $data) use ($http_worker) {
                //获取用户传输过来的数据,并且进行json_decode解析
                $data = json_decode($data, true);
                //获取用户ID接着将用户信息$connection,存储在$http_worker->uidConnections中,
                //$http_worker->uidConnections[$data['id']] = $connection;
                $connection->uid = $data['user_type'].'_'.$data['id'];
                $uid = $data['user_type'].'_'.$data['id'];// 发送者user_id
                // Log::info($uid);
                $http_worker->uidConnections[$uid] = $connection;
                //给其他用户发送,该用户发送的信息,为了保持数据的实时性。
                try {
                    DB::beginTransaction();
                    $uid_key = 'enterpriseUser_'. $data['fid'];// 接收者user_type._.fid
                    foreach ($http_worker->uidConnections as $k => $v) {
                        if($k == $uid_key){
                            $v->send(json_encode(['status' => 0, 'msg' => $data['content']]));
                        }
                    }
                    DB::commit();
                } catch (Exception $exception) {
                    Log::info($exception);
                    DB::rollBack();
                }
            };
            //设置用户断开连接的回调。
            $connection->onClose = function ($connection) use ($http_worker) {
                foreach ($http_worker->uidConnections as $k => $v) {
                    if ($v == $connection) {
                        unset($http_worker->uidConnections[$k]);
                    } else {
                        $v->send(json_encode(['status' => 0, 'msg' => $k . '下线了']));
                    }
                }
            };
            /*设置心跳,为防止长链接断开      * 原理:就是设置一个定时器,定时的向客户端发送数据      * $time_interval 时间间隔* */
            $time_interval = 59;
            Timer::add($time_interval, function () use ($http_worker) {
                if (count($http_worker->uidConnections) > 0) {
                    foreach ($http_worker->uidConnections as $connection) {
                        $connection->send(json_encode(['status' => 1, 'smg' => 'socket_hot']));
                    }
                }
            });
        };
        Worker::runAll();
    }
}

前端js

onMounted(() => {
  alert('请登录')
  var url = 'ws://127.0.0.1:2001'
  var ws = new WebSocket(url)
  var user_id = 74620
  var id = 'jobSeekerUser_' + user_id
  ws.onopen = function () {
    var data = {id: user_id, user_type: 'jobSeekerUser', is_true: false }
    data = JSON.stringify(data)
    ws.send(data)
  }
  ws.onmessage = function (e) {
    var msg = JSON.parse(e.data)
    if (msg.status == 200) {
      console.log(msg.msg)
    }
  }
})
// 发送方法待调用
function this_test(type = 1, content = '', request_status = 1, user_id = 74620, fid = 2, user_type = 'jobSeekerUser', image_url = '', recruits_id = 0, resumes_id = 0, is_true = true) {
  var url = 'ws://127.0.0.1:2001' 
  var ws = new WebSocket(url)// 调用了两次待优化
  var id = 'jobSeekerUser_' + user_id
  var tests = this
  ws.onopen = function () {// 事件封装请求方法
    var data = {
      id: user_id,//发送者uid
      // uid: id,//请求身份识别jobSeekerUser_id
      content: content,
      fid: fid,//接收者id
      user_type: user_type,//jobSeekerUser
      type: type, // 消息类型(1文字)
      status: request_status,// 请求状态1发送2接收
      image_url: image_url,// 图片链接
      recruits_id: recruits_id,// 职位招聘信息id
      resumes_id: resumes_id, //简历id
      is_true: is_true// 是否发送消息请求
    }
    data = JSON.stringify(data)
    ws.send(data)// 发送
  }
  ws.onmessage = function (e) {
    var msg = JSON.parse(e.data)
    if (msg.status == 200) {
      console.log(msg.msg)
    }
  }
}