windows如何实例两个worker(socket worker 与 websocket worker如何通讯)

xiawei308

windows如何实例两个worker

图片

现在要实例如上图的应用,只是简单DEMO用。workerman一个实例worker2(自定义协议)用来与设备通信,另一个实例worker1(websocker)用来与前端页面通信,通过前端页面给worker2指令,并将worker2收到的数据表现在前端页面。

//ini_set("error_reporting","E_ALL & ~E_NOTICE"); 
use Workerman\Worker;
require_once __DIR__ . '/../../Workerman/Autoloader.php';

// 创建一个Worker监听2347端口,不使用任何应用层协议
$worker1 = new Worker("Websocket://0.0.0.0:23456");
$worker2 = new Worker("tcp://0.0.0.0:5555");

// 启动1个进程对外提供服务
$worker1->count = 1;
$worker2->count = 1;

// 当客户端发来数据时
$worker1->onMessage = function($connection, $data)
{
    // 向客户端发送hello $data
    echo $data;
};

$worker2->onMessage = function($connection, $data)
{
    // 向客户端发送hello $data
    echo $data;
};

// 当有客户端连接上服务器
$worker1->onConnect = function($connection)
{
    echo "new connection from ip " . $connection->getRemoteIp() . "\n";

    //$inverter_s310 = new Inverter();
    //$inverter_s310->setFrequency($connection,50);
};

// 当有客户端连接上服务器
$worker2->onConnect = function($connection)
{
    echo "TCP new connection from ip " . $connection->getRemoteIp() . "\n";

    //$inverter_s310 = new Inverter();
    //$inverter_s310->setFrequency($connection,50);
};

// 运行worker
Worker::runAll();

-以上是TEST代码,但发现只有一个worker有用,另一个无法操作。

9136 3 0
3个回答

walkor

由于widows下的php没有完善的进程控制接口,导致windows版本无法在一个启动脚本中实例化多个容器(Worker\WebServer\Gateway\BusinessWorker)进程。解决方法是使用多个启动脚本,每个脚本启动实例化一个容器。

假设初始化两个Worker实例,则创建两个启动文件 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....
 ...

启动时就可以像这样,直接启动两个脚本,(在cmd命令行中运行)
php socket_server.php websocket_server.php

  • 暂无评论
walkor

上面示例中初始化了两个进程,一个是socket通讯进程,一个是websocket通讯进程,然而根据你的应用实际上是要一个Worker进程,同时支持两种通讯,这样才方便websocket与socket之间的通讯。所以根据你的实际情况,应该初始化一个同时支持两种通讯方法的Worker进程。方法如下:

<?php
use Workerman\Worker;
require_once __DIR__ . '/Workerman/Autoloader.php';
// websocket 协议的worker
$ws_worker = new Worker('Websocket://0.0.0.0:5656');
// 这里只能写1
$ws_worker->count = 1;
// websocket server 启动后在当前进程增加一个socket监听
$ws_worker->onWorkerStart = function($ws_worker)
{
    // 增加一个Socket端口的监听设备发来的数据
    $socket_worker = new Worker('tcp://0.0.0.0:5555');
    // 当设备发来数据时如何处理
    $socket_worker->onMessage = function($connection, $data)
    {
        // 这里处理设备发来的数据 $data
        // 比如像这样给所有的WebSocket连接转发数据
        global $ws_worker;
        foreach($ws_worker->connections as $ws_con)
        {
            $ws_con->send($data);
        }
    };
    // 给ws_worker添加一个属性保存socket_worker,方便获取
    $ws_worker->socketWorker = $socket_worker;
    // 执行监听
    $socket_worker->listen();
};

// websocket协议也就是浏览器发来数据时
$ws_worker->onMessage = function($connection, $data)
{
    // 假设需要转发给所有的设备
    global $ws_worker;
    foreach($ws_worker->socketWorker->connections as $socket_con)
    {
        $socket_con->send($data);
    }
};

Worker::runAll();

上面这个例子是一个进程同时监听多协议多个端口的例子,这样socket 与 websocket之间通讯就会非常方方便,直接内存调用即可。这个例子中业务罗辑为广播,socket可以使用telnet 测试,websocket用浏览器测试,telnet与浏览器之间就可以互相通讯了,如果要针对某个特定设备推送数据,可以参考
http://wenda.workerman.net/question/432

最后注意尽量不要用原生tcp通讯,会有粘包问题,可以用Workerman的Text协议代替(new Worker('Text://0.0.0.0:55555')),协议规则很简单,
文本+换行符,与telnet兼容。

  • 暂无评论
walkor
  • jinnstyl 2018-11-27

    你好walkor, 这种方式如何做分布式系统呢?

年代过于久远,无法发表回答
🔝