laravel集成Workerman搭建websocket服务,前端调用,服务器启动

laravel集成Workerman搭建websocket服务,前端调用,服务器启动

码农世界 2024-06-05 前端 105 次浏览 0个评论

本文有相对完整的集成代码和前端测试代码,以及服务器启动注意事项

一、后端(laravel5.5)

1、composer安装Workerman

composer require workerman/workerman

2、生成执行命令,执行后会在App\Console\Command文件夹下生成一个Workerman.php的文件

php artisan make:command Workerman

3、打开Workerman.php的文件,并修改代码,如下:

argument('action');
        $argv[1] = $arg;
        $argv[2] = $this->option('daemonize') ? '-d' : '';//该参数是以daemon(守护进程)方式启动
        global $text_worker;
        // 创建一个Worker监听9991端口,使用websocket协议通讯
        $text_worker = new Worker("websocket://0.0.0.0:9991");
        $text_worker->uidConnections = array();//在线用户连接对象
        $text_worker->uidInfo = array();//在线用户的用户信息
        // 启动4个进程对外提供服务
        $text_worker->count = 1;
        //当启动workerman的时候 触发此方法
        $text_worker->onWorkerStart =function(){
            //监听一个内部端口,用来接收服务器的消息,转发给浏览器
            $inner_text_worker = new Worker('text://127.0.0.1:5678');
            $inner_text_worker->onMessage = function($connection_admin, $data)
            {
                global $text_worker;
                // $data数组格式,里面有uid,表示向那个uid的页面推送数据
                $buffer = json_decode($data, true);
                //var_dump($buffer);
                $to_uid = $buffer['to_uid'];
                //var_dump($to_uid);
                // 通过workerman,向uid的页面推送数据
                if(isset($text_worker->uidConnections[$to_uid])){
                    $connection = $text_worker->uidConnections[$to_uid];
                    $ret = $connection->send($data);
                } else {
                    var_dump($to_uid . ': not define');
                    $ret = false;
                }
                // 返回推送结果
                $connection_admin->send($ret ? 'ok' : 'fail');
            };
            $inner_text_worker->listen();
            // 进程启动后设置一个每10秒运行一次的定时器
            Timer::add(10, function(){
                global $text_worker;
                $time_now = time();
                foreach($text_worker->connections as $connection) {
                    // 有可能该connection还没收到过消息,则lastMessageTime设置为当前时间
                    if (empty($connection->lastMessageTime)) {
                        $connection->lastMessageTime = $time_now;
                        continue;
                    }
                    // 上次通讯时间间隔大于心跳间隔,则认为客户端已经下线,关闭连接
                    if ($time_now - $connection->lastMessageTime > HEARTBEAT_TIME) {
                        var_dump("delete:" . $connection->uid);
                        unset($text_worker->uidConnections["{$connection->uid}"]);
                        $connection->close();
                    }
                }
            });
        };
        //当浏览器连接的时候触发此函数
        $text_worker->onConnect = function($connection) {
        };
        //向用户发送信息的时候触发
        //$connection 当前连接的人的信息 $data 发送的数据
        $text_worker->onMessage = function($connection,$data){
            // 给connection临时设置一个lastMessageTime属性,用来记录上次收到消息的时间
            $connection->lastMessageTime = time();
            // 其它业务逻辑...
            $data = json_decode($data, true);
            if($data['type']=='login') {
                $this->create_uid($connection,$data);
            }
            if($data['type']=='send_message'){
                $this->send_message($connection,$data);
            }
        };
        //浏览器断开链接的时候触发
        $text_worker->onClose = function($connection){};
        Worker::runAll();
    }
    //创建uid方法
    public function create_uid($connection,$data){
        global $text_worker;
        $connection->uid = $data['uid'];
        //保存用户的uid
        $text_worker->uidConnections["{$connection->uid}"] = $connection;
        //向自己的浏览器返回创建成功的信息
        $connection->send(json_encode([
            "uid"=>$connection->uid,
            "msgType"=>'text',
            "content"=>'聊天创建成功,您可以开发发送消息了'
        ]));
    }
    public function send_message($connection,$data) {
        global $text_worker;
        if(isset($data['to_uid'])){
            if(isset($text_worker->uidConnections["{$data['to_uid']}"])){
                $to_connection=$text_worker->uidConnections["{$data['to_uid']}"];
                $to_connection->send(json_encode([
                    "uid"=>$data['uid'],
                    "msgType"=>$data['msgType'],
                    "content"=>$data['message']
                ]));
            }
        }
    }
}

4、修改App\Console下面的Kernel.php文件,如下:

protected $commands = [
        Commands\Workerman::class,
];

5、启动Workerman服务,启动命令如下:

php artisan Workerman start

出现上图所示,则表示启动成功

二、前端如何连接Workerman服务(websocket)服务

1、新建两个html页面用于测试,当然,也可以直接在浏览器打开F12在console里面测试,我这里有写好的页面,直接换个ws地址就能用,支持发送文字,图片

37websoket.html




  
  
  
   


  
    
      
        
          
            
          
          
            {{item.content}}
          
          
            
          
        
        
          
            {{item.content}}
          
          
            
          
          
            
          
        
      
    
    
  	
        
        
          
          发消息
          
        
    
  
  


38websoket.html




  
  
  
   


  
    
      
        
          
            
          
          
            {{item.content}}
          
          
            
          
        
        
          
            {{item.content}}
          
          
            
          
          
            
          
        
      
    
    
    
        
        
          
          发消息
          
        
    
  
  


分别保存为两个html文件,两个都在浏览器打开,页面上出现 “聊天创建成功,您可以开发发送消息了”,则说明连接成功,可以正常发消息了

至此调试完成!

三、在服务器运行Workerman服务

我们本地调试完成后,最终需要上传到服务器上去运行,例如:Centos,服务上也需要composer安装Workerman,方式和最开头一样,我直接说说如何启动

在服务器上启动Workerman和在本地有一定的区别,因为通常我们希望在服务器上,Websocket能一直处于启动状态,所以,上述所说的启动命令,要稍微改一下,即在命令后加上:--daemonize(守护进程启动)

php artisan Workerman start --daemonize (关掉终端,服务不会停止)
php artisan Workerman stop --daemonize (服务停止)
php artisan Workerman start (关掉终端,服务会停止)
php artisan Workerman stop (服务停止)

至此,laravel集成Workerman搭建websocket服务已完成

 本文参考文章:laravel与workerman结合_laravel workerman-CSDN博客

转载请注明来自码农世界,本文标题:《laravel集成Workerman搭建websocket服务,前端调用,服务器启动》

百度分享代码,如果开启HTTPS请参考李洋个人博客
每一天,每一秒,你所做的决定都会改变你的人生!

发表评论

快捷回复:

评论列表 (暂无评论,105人围观)参与讨论

还没有评论,来说两句吧...

Top