本文有相对完整的集成代码和前端测试代码,以及服务器启动注意事项
一、后端(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博客
还没有评论,来说两句吧...