windows如何實(shí)例兩個(gè)worker
現(xiàn)在要實(shí)例如上圖的應(yīng)用,只是簡(jiǎn)單DEMO用。workerman一個(gè)實(shí)例worker2(自定義協(xié)議)用來(lái)與設(shè)備通信,另一個(gè)實(shí)例worker1(websocker)用來(lái)與前端頁(yè)面通信,通過(guò)前端頁(yè)面給worker2指令,并將worker2收到的數(shù)據(jù)表現(xiàn)在前端頁(yè)面。
//ini_set("error_reporting","E_ALL & ~E_NOTICE");
use Workerman\Worker;
require_once __DIR__ . '/../../Workerman/Autoloader.php';
// 創(chuàng)建一個(gè)Worker監(jiān)聽(tīng)2347端口,不使用任何應(yīng)用層協(xié)議
$worker1 = new Worker("Websocket://0.0.0.0:23456");
$worker2 = new Worker("tcp://0.0.0.0:5555");
// 啟動(dòng)1個(gè)進(jìn)程對(duì)外提供服務(wù)
$worker1->count = 1;
$worker2->count = 1;
// 當(dāng)客戶端發(fā)來(lái)數(shù)據(jù)時(shí)
$worker1->onMessage = function($connection, $data)
{
// 向客戶端發(fā)送hello $data
echo $data;
};
$worker2->onMessage = function($connection, $data)
{
// 向客戶端發(fā)送hello $data
echo $data;
};
// 當(dāng)有客戶端連接上服務(wù)器
$worker1->onConnect = function($connection)
{
echo "new connection from ip " . $connection->getRemoteIp() . "\n";
//$inverter_s310 = new Inverter();
//$inverter_s310->setFrequency($connection,50);
};
// 當(dāng)有客戶端連接上服務(wù)器
$worker2->onConnect = function($connection)
{
echo "TCP new connection from ip " . $connection->getRemoteIp() . "\n";
//$inverter_s310 = new Inverter();
//$inverter_s310->setFrequency($connection,50);
};
// 運(yùn)行worker
Worker::runAll();
-以上是TEST代碼,但發(fā)現(xiàn)只有一個(gè)worker有用,另一個(gè)無(wú)法操作。
由于widows下的php沒(méi)有完善的進(jìn)程控制接口,導(dǎo)致windows版本無(wú)法在一個(gè)啟動(dòng)腳本中實(shí)例化多個(gè)容器(Worker\WebServer\Gateway\BusinessWorker)進(jìn)程。解決方法是使用多個(gè)啟動(dòng)腳本,每個(gè)腳本啟動(dòng)實(shí)例化一個(gè)容器。
假設(shè)初始化兩個(gè)Worker實(shí)例,則創(chuàng)建兩個(gè)啟動(dòng)文件 socket_server.php 和 websocket_server.php
例如:
socket_server.php
...
$socket_server = new Worker("tcp://0.0.0.0:5555");
$socket_server->on....
....
websocket_server.php
$websocket_server = new Worker("tcp://0.0.0.0:6666");
$websocket_server->on....
...
啟動(dòng)時(shí)就可以像這樣,直接啟動(dòng)兩個(gè)腳本,(在cmd命令行中運(yùn)行)
php socket_server.php websocket_server.php
上面示例中初始化了兩個(gè)進(jìn)程,一個(gè)是socket通訊進(jìn)程,一個(gè)是websocket通訊進(jìn)程,然而根據(jù)你的應(yīng)用實(shí)際上是要一個(gè)Worker進(jìn)程,同時(shí)支持兩種通訊,這樣才方便websocket與socket之間的通訊。所以根據(jù)你的實(shí)際情況,應(yīng)該初始化一個(gè)同時(shí)支持兩種通訊方法的Worker進(jìn)程。方法如下:
<?php
use Workerman\Worker;
require_once __DIR__ . '/Workerman/Autoloader.php';
// websocket 協(xié)議的worker
$ws_worker = new Worker('Websocket://0.0.0.0:5656');
// 這里只能寫1
$ws_worker->count = 1;
// websocket server 啟動(dòng)后在當(dāng)前進(jìn)程增加一個(gè)socket監(jiān)聽(tīng)
$ws_worker->onWorkerStart = function($ws_worker)
{
// 增加一個(gè)Socket端口的監(jiān)聽(tīng)設(shè)備發(fā)來(lái)的數(shù)據(jù)
$socket_worker = new Worker('tcp://0.0.0.0:5555');
// 當(dāng)設(shè)備發(fā)來(lái)數(shù)據(jù)時(shí)如何處理
$socket_worker->onMessage = function($connection, $data)
{
// 這里處理設(shè)備發(fā)來(lái)的數(shù)據(jù) $data
// 比如像這樣給所有的WebSocket連接轉(zhuǎn)發(fā)數(shù)據(jù)
global $ws_worker;
foreach($ws_worker->connections as $ws_con)
{
$ws_con->send($data);
}
};
// 給ws_worker添加一個(gè)屬性保存socket_worker,方便獲取
$ws_worker->socketWorker = $socket_worker;
// 執(zhí)行監(jiān)聽(tīng)
$socket_worker->listen();
};
// websocket協(xié)議也就是瀏覽器發(fā)來(lái)數(shù)據(jù)時(shí)
$ws_worker->onMessage = function($connection, $data)
{
// 假設(shè)需要轉(zhuǎn)發(fā)給所有的設(shè)備
global $ws_worker;
foreach($ws_worker->socketWorker->connections as $socket_con)
{
$socket_con->send($data);
}
};
Worker::runAll();
上面這個(gè)例子是一個(gè)進(jìn)程同時(shí)監(jiān)聽(tīng)多協(xié)議多個(gè)端口的例子,這樣socket 與 websocket之間通訊就會(huì)非常方方便,直接內(nèi)存調(diào)用即可。這個(gè)例子中業(yè)務(wù)羅輯為廣播,socket可以使用telnet 測(cè)試,websocket用瀏覽器測(cè)試,telnet與瀏覽器之間就可以互相通訊了,如果要針對(duì)某個(gè)特定設(shè)備推送數(shù)據(jù),可以參考
http://wenda.workerman.net/question/432
最后注意盡量不要用原生tcp通訊,會(huì)有粘包問(wèn)題,可以用Workerman的Text協(xié)議代替(new Worker('Text://0.0.0.0:55555')),協(xié)議規(guī)則很簡(jiǎn)單,
文本+換行符,與telnet兼容。