我的需求是:
某裝置通過8093端口向伺服器推送事件資訊;
伺服器通過8093端口接收事件提取有用的資訊再通過8090端口向web端推送資訊;
web端通過8090端口接受資訊幫完成響應的動作;
我遇到的難題:
需要監聽8090端口和8093端口,但是這是兩個不同的程序,變量資料不共享;
向8090端口推送消息可以主動推送,不需要回調;
解決方案:
Workerman是一款純PHP開發的開源高性能的PHP socket 服務架構。
http://doc.workerman.net/
用的是workerman的Channel分布式通訊元件解決方案
代碼:
<?php
use Workerman\Worker;
require_once __DIR__ . '/Workerman/Autoloader.php';
require_once __DIR__ . '/Channel/src/Server.php';
require_once __DIR__ . '/Channel/src/Client.php';
// 初始化一個Channel服務端
$channel_server = new Channel\Server('0.0.0.0', 2206);
// websocket服務端
$worker = new Worker('websocket://0.0.0.0:8090');
$worker->count=1;
$worker->name = 'pusher';
$worker->onWorkerStart = function($worker)
{
// Channel用戶端連接配接到Channel服務端
Channel\Client::connect('0.0.0.0', 2206);
// 訂閱廣播事件
$event_name = 'sendWeb';
Channel\Client::on($event_name, function($event_data)use($worker){
$message = $event_data['content'];
// echo $message;
//向訂閱了sendWeb事件的用戶端推送資訊
foreach($worker->connections as $connection)
{
$connection->send(json_encode($message));
}
});
};
$worker->onConnect = function($connection)use($worker)
{
$msg = "workerID:{$worker->id} connectionID:{$connection->id} connected\n";
echo $msg;
$info = array("workerID"=>$worker->id,
"connectionID"=>$connection->id);
$connection->send(json_encode($info));
};
//監聽來自OM20的事件,并把監聽到的資料通過channel服務端推送給訂閱了事件的程序
$http_worker = new Worker('tcp://0.0.0.0:8093');
$http_worker->name = 'publisher';
//程序啟動時就連上channel服務端
$http_worker->onWorkerStart = function()
{
Channel\Client::connect('0.0.0.0', 2206);
};
$http_worker->onMessage = function($connection, $data)
{
$connection->send('ok');
if(empty($data))
{
echo "data is null ";
return;
}
// echo "8093....................................................\n";
//通過channel服務端推送給訂閱了sendWeb事件的程序
$event_name = 'sendWeb';
Channel\Client::publish($event_name, array(
'content' => $info
));
// echo $data;
};
Worker::runAll();
對代碼的了解:
1.要建立一個channel端(2206端口),我的了解是這個channel就像一個中轉站,程序間的變量共享問題就是通過這個channel解決的。
2.2206向8090推送事件資訊;但是這個推送不是誰都要推送,隻會向訂閱了用戶端推送資訊,是以8090要向2206訂閱一個事件,我是命名為sendWeb了。
3.從8093收到事件資訊就向2206推送;這個推送是向某個事件(sendWeb)進行推送。
前端代碼為:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<h3>WebSocket協定的用戶端程式</h3>
<button id="btConnect">連接配接到WS伺服器</button>
<button id="btSendAndReceive">向WS伺服器發消息并接收消息</button>
<button id="btClose">斷開與WS伺服器的連接配接</button>
<div id="val"></div>
<script>
var wsClient = null; //WS用戶端對象
wsClient = new WebSocket('ws://10.63.15.169:8090');
wsClient.onopen = function(){
console.log('成功連接配接伺服器')
}
wsClient.onmessage = function(res){
let ret = JSON.parse(res.data);
console.log('data.data為:'+ res.data)
}
wsClient.onerror = function(){
console.log('通信發生錯誤')
}
btClose.onclick = function(){
//斷開到WS伺服器的連接配接
wsClient.close(); //向伺服器發消息,主動斷開連接配接
wsClient.onclose = function(){
//經過用戶端和伺服器的四次揮手後,二者的連接配接斷開了
console.log('到伺服器的連接配接已經斷開')
}
}
</script>
</body>
</html>
所有代碼本人親測有效