laravel使用workerman 使用者互動、伺服器互動
使用workeman實現瀏覽器相互通訊、伺服器瀏覽器互動
一、安裝workerman
composer require workerman/workerman
二、生成命令檔案
php artisan make:command Workerman
修改檔案
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Workerman\Worker;
class Workerman extends Command
{
protected $signature = 'Workerman {action} {--daemonize}';
protected $description = 'Command description';
public function __construct()
{
parent::__construct();
}
public function handle()
{
global $argv;//定義全域性變數
$arg = $this->argument('action');
$argv[1] = $arg;
$argv[2] = $this->option('daemonize') ? '-d' : '';//該引數是以daemon(守護程式)方式啟動
global $text_worker;
// 建立一個Worker監聽2345埠,使用websocket協議通訊
$text_worker = new Worker("websocket://0.0.0.0:2345");
$text_worker->uidConnections = array();//線上使用者連線物件
$text_worker->uidInfo = array();//線上使用者的使用者資訊
// 啟動4個程式對外提供服務
$text_worker->count = 4;
//當啟動workerman的時候 觸發此方法
$text_worker->onWorkerStart =function(){
};
//當瀏覽器連線的時候觸發此函式
$text_worker->onConnect = function($connection){
};
//向使用者傳送資訊的時候觸發
//$connection 當前連線的人的資訊 $data 傳送的資料
$text_worker->onMessage = function($connection,$data){
};
//瀏覽器斷開連結的時候觸發
$text_worker->onClose = function($connection){};
}
}
三、啟動命令
$ php artisan Workerman start --daemonize
Deprecated: Directive 'track_errors' is deprecated in Unknown on line 0
----------------------- WORKERMAN -----------------------------
Workerman version:4.0.19 PHP version:7.2.9
------------------------ WORKERS -------------------------------
worker listen processes status
none websocket://0.0.0.0:2345 4 [ok]
四、瀏覽器之間通訊
1. HTML程式碼 兩個html做互動
var socket = new WebSocket("ws://localhost:2345//ws");
// 建立連線時觸發 建立連結的時候,需要向workerman傳送一條指令,告訴他我是誰,使用id或者使用者標識作為uid,告訴workerman 例如,當前html 使用者id是37
socket.onopen = function(event) {
console.log('連線開始...');
socket.send('{"uid":36,"type":'login'}');
}
//workerman傳送訊息的時候,接收並列印
socket.onmessage = function(event) {
var msg = event.data;
console.log(msg );
}
2. 設定uid
瀏覽器發來了使用者uid,需要workerman保留一下,網上有文件說在觸發的時候儲存,還有用session的,我試驗了沒成功,所有用瀏覽器建立連結的時候,向workerman傳送一條資訊來建立uid,在workerman上接收一下
//$connection 當前連線的人的資訊 $data 傳送的資料
$text_worker->onMessage = function($connection,$data){
$data = json_decode($data);
if($data['type']=='login'){
$this->create_uid($connection,$data);
}
};
//建立uid方法
public function create_uid($connection,$data){
global $text_worker;
$connection->uid = $data['uid'];
//儲存使用者的uid
$text_worker->uidConnections["{$connection->uid}"] = $connection;
//向自己的瀏覽器返回建立成功的資訊
$connection->send("使用者:[{$connection->uid}] 建立成功");
}
這時候瀏覽器就會出現列印資訊
3. 向其他使用者傳送資訊
向使用者是37的瀏覽器傳送資訊
//js程式碼
socket.send('{"type":"login","to_uid":36,"uid":36,"message":"nihao"}');
//workerman
//$connection 當前連線的人的資訊 $data 傳送的資料
$text_worker->onMessage = function($connection,$data){
$data = json_decode($data,true);
var_dump($data);
if($data['type']=='login'){
$this->create_uid($connection,$data);
}
if($data['type']=='send_message'){
$this->send_message($connection,$data);
}
};
public function send_message($connection,$data){
global $text_worker;
if(isset($data['to_uid'])){
var_dump($data['to_uid']);
if(isset($text_worker->uidConnections["{$data['to_uid']}"])){
$to_connection=$text_worker->uidConnections["{$data['to_uid']}"];
$to_connection->send($data['uid'].$data['message']);
}
}
}
五、伺服器向瀏覽器通訊
1. workeman監聽一個本地傳送的埠,在啟動的時候
//當啟動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的頁面推送資料
$data = json_decode($data, true);
var_dump($data);
$to_uid = $data['to_uid'];
var_dump($to_uid);
// 通過workerman,向uid的頁面推送資料
// $ret = sendMessageByUid($uid, $buffer);
$connection = $text_worker->uidConnections[$to_uid];
$connection->send($buffer);
// 返回推送結果
$connection_admin->send(true ? 'ok' : 'fail');
};
$inner_text_worker->listen();
};
//控制器程式碼
class TestController extends Controller
{
public function send(){
$client = stream_socket_client('tcp://127.0.0.1:5678', $errno, $errmsg, 1);
// 推送的資料,包含使用者,表示是給這個使用者推送
$data = array('uid'=>37,'group'=>'admin', 'message'=>'傳送成功啦');
// 傳送資料,注意5678埠是Text協議的埠,Text協議需要在資料末尾加上換行符
fwrite($client, json_encode($data)."\n");
}
}
結語
有不足之處,請大家指正!謝謝!
本作品採用《CC 協議》,轉載必須註明作者和本文連結