php – Workerman – 使用 Websocket 廣播給所有客戶端
預設只推送給 connect 單一 client 端,那如果要推送給所有人呢?可以藉由搭配訂閱的功能。
除了透過 composer 安裝 workerman 之外,還需要安裝 Channel分佈式通訊組件: workerman/channel
composer require workerman/workerman
composer require workerman/channel
接著貼上 start.php
<?php
require_once __DIR__ . '/vendor/autoload.php';
use Workerman\Worker;
use Channel\Client;
use Channel\Server;
// 初始化一个Channel服务端
$channel_server = new Server('0.0.0.0', 2206);
// Create a Websocket server
$ws_worker = new Worker("websocket://0.0.0.0:2346");
// 4 processes
$ws_worker->count = 4;
$ws_worker->onWorkerStart = function ($worker) {
// Channel客户端连接到Channel服务端
Client::connect('0.0.0.0', 2206);
// 订阅broadcast事件,并注册事件回调
Client::on('broadcast', function ($event_data) use ($worker) {
// 向当前worker进程的所有客户端广播消息
foreach ($worker->connections as $connection) {
$connection->send($event_data);
}
});
};
// Emitted when data received
$ws_worker->onMessage = function ($connection, $data) use ($ws_worker) {
// 向所有worker进程发布broadcast事件
Channel\Client::publish('broadcast', $data);
};
// Emitted when connection closed
$ws_worker->onClose = function ($connection) {
echo "Connection closed\n";
};
// Run worker
Worker::runAll();
接著啟動服務,我們透過 php 運行
php start.php
建立 Client 端部分
<input type="text" class="name" placeholder="請輸入姓名" autofocus>
<input type="submit" value="發送" onclick="send_msg(); ">
var wsServer = 'ws://0.0.0.0:2346';
var websocket = new WebSocket(wsServer);
websocket.onopen = function (evt) {
console.log("成功連接到 WebSocket 服務");
};
websocket.onclose = function (evt) {
console.log("關閉連接 WebSocket 服務");
};
websocket.onmessage = function (evt) {
console.log('伺服器顯示:' + evt.data);
};
websocket.onerror = function (evt, e) {
console.log('發生錯誤: ' + evt.data);
};
// 發送訊息給所有人
const send_msg = function (){
var name = document.getElementsByClassName('name')[0].value;
var msg = JSON.stringify({
message: '你好,我是' + name,
})
websocket.send(msg)
}