【thinkphp+workerman实现tcp接收数据处理并转发给websocket推送前端】

7 篇文章 0 订阅
6 篇文章 0 订阅

安装workerman

composer require workerman/workerman
composer require workerman/workerman-for-win

由于是windows环境,所以要写两个文件才能起来两个worker服务

新建TCP使用的控制器文件

application/worker(自己需要的目录)/Worker.php

此文件将硬件的数据通过tcp接收进来,处理后转发给websocket和存储数据库

<?php

namespace app\worker\controller;

use GatewayClient\GatewayProtocol;
use think\worker\Server;
use GatewayClient\Gateway;
use Workerman\Connection\AsyncTcpConnection;
use Workerman\Lib\Timer;
use Workerman\Protocols\Ws;

date_default_timezone_set("PRC");

class Worker extends Server
{
    protected $socket = 'tcp://127.0.0.1:24001';

    protected $processes = 1;

    public $ws_server;

    protected static $heartbeat_time    =   30;

    /**
     * 每个进程启动
     * @param $worker
     */
    public function onWorkerStart($worker)
    {
        echo "TCP服务启动了\n";

        // 以websocket协议连接远程websocket服务器
        $ws_connection = new AsyncTcpConnection("ws://127.0.0.1:21001");
        // 每隔55秒向服务端发送一个opcode为0x9的websocket心跳(可选)
        $ws_connection->websocketPingInterval = 30;
        // 设置http头(可选)
        $ws_connection->headers = [
            'Cookie' => 'PHPSID=82u98fjhakfusuanfnahfi; token=2hf9a929jhfihaf9i',
            'OtherKey' => 'values'
        ];
        // 设置数据类型(可选)
        $ws_connection->websocketType = Ws::BINARY_TYPE_BLOB; // BINARY_TYPE_BLOB为文本 BINARY_TYPE_ARRAYBUFFER为二进制
        // 当TCP完成三次握手后(可选)
        $ws_connection->onConnect = function($connection){
            echo "websocket connected\n";
        };
        // 当websocket完成握手后(可选)
        $ws_connection->onWebSocketConnect = function(AsyncTcpConnection $con, $response) {
            echo $response;
            $con->send('websocket连接成功');
        };
        // 远程websocket服务器发来消息时
        $ws_connection->onMessage = function($connection, $data){
            echo "来自websocket服务器的消息: $data\n";
        };
        // 连接上发生错误时,一般是连接远程websocket服务器失败错误(可选)
        $ws_connection->onError = function($connection, $code, $msg){
            echo "错误: $msg\n";
        };
        // 当连接远程websocket服务器的连接断开时(可选,建议加上重连)
        $ws_connection->onClose = function($connection){
            echo "连接已关闭并尝试重新连接\n";
            // 如果连接断开,1秒后重连
            $connection->reConnect(1);
        };
        // 设置好以上各种回调后,执行连接操作
        $ws_connection->connect();

        $this->ws_server =  $ws_connection;

//        //心跳检测---服务端不需要
//        Timer::add(3, function()use($worker){
//            $time_now   =   time();
//            foreach ($worker->connections as $connection) {
//                if (empty($connection->lastMessageTime)) {
//                    $connection->lastMessageTime = $time_now;
//                }
//                #判断心跳时间
//                if ($time_now - $connection->lastMessageTime > self::$heartbeat_time) {
                    $connection->send(1);
                    $connection->close();
//                }
                $connection->send('heartbeat');
//            }
//
//        });
    }

    /**
     * 收到信息
     * @param $connection
     * @param $data
     */
    public function onMessage($connection, $data)
    {
        $connection->lastMessageTime = time();
        #处理$data的逻辑业务

        $ws_data = '数据';
        

        #转发websocket数据
        $ws_arr = [
            'code' => 1,
            'msg'  => 'ok',
            'time' => time(),
            'data' => ['content' => $ws_data]
        ];
        $this->ws_server->send(json_encode($ws_arr, 256) . "\r\n");

        echo "转发websocket成功!";

        #回复消息
        $connection->lastMessageTime = time();
        $connection->send(json_encode('获得成功'));


    }

    /**
     * 当连接建立时触发的回调函数
     * @param $connection
     */
    public function onConnect($connection)
    {

        echo "连接 建立" . $connection->getRemoteIp() . ":". $connection->getRemotePort() ."\n";
        $connection->send(json_encode('connect success'));
    }

    /**
     * 当连接断开时触发的回调函数
     * @param $connection
     */
    public function onClose($connection)
    {
        echo "连接 关闭\n";
        #断线1秒后重新连接
        $connection->reConnect(1);
    }

    /**
     * 当客户端的连接上发生错误时触发
     * @param $connection
     * @param $code
     * @param $msg
     */
    public function onError($connection, $code, $msg)
    {
        echo "错误: $code $msg\n";
    }


    public function onWorkerReload($worker)
    {
        foreach($worker->connections as $connection)
        {
            $connection->send('worker reloading');
        }
    }
}

新建Websocket使用的控制器文件

application/worker(自己需要的目录)/Websocket.php

此文件将websocket接收到到的数据发给客户端

<?php

namespace app\worker\controller;

use think\worker\Server;

date_default_timezone_set("PRC");

class Websecket extends Server
{
    protected $socket = 'Websocket://127.0.0.1:21001';

    protected $processes = 4;

    protected static $heartbeat_time    =   30;

    public $userlist=[];

    /**
     * 收到信息
     * @param $connection
     * @param $data
     */
    public function onMessage($connection, $data)
    {
        global $worker;
        $fd = $connection->id;

        echo '收到来自_id='.$fd.'_客户端的消息:'.$data."\r\n";
        $connection->lastMessageTime = time();

        if(!isset($connection->uid)){
            $connection->uid=$connection->id;  //此处为了方便测试把会话id作为用户id  详情见官方文档
            $connection->worker->connections[$connection->uid] = $connection;
        }

        // 遍历当前进程所有的客户端连接
        foreach($connection->worker->connections as $key=> $con)
        {
        //
            if ($key != $fd){
//                echo $con->id.'--------'.$connection->id;
//                continue;
                echo $con->id.'======'.$connection->id;
                $con->send($data);
            }
        }

    }

    /**
     * 当连接建立时触发的回调函数
     * @param $connection
     */
    public function onConnect($connection)
    {
        echo "websocket连接 建立:".$connection->getRemoteIp() . ":". $connection->getRemotePort()."{$connection->id}\n";
        $connection->send(json_encode('websocket connect success'));
    }

    /**
     * 当连接断开时触发的回调函数
     * @param $connection
     */
    public function onClose($connection)
    {
        echo "websocket连接 关闭\n";
        $connection->reConnect(1);
    }

    /**
     * 当客户端的连接上发生错误时触发
     * @param $connection
     * @param $code
     * @param $msg
     */
    public function onError($connection, $code, $msg)
    {
        echo "websocket错误: $code $msg\n";
    }

    /**
     * 每个进程启动
     * @param $worker
     */
    public function onWorkerStart($worker)
    {
        echo "WebSocket服务启动了\n";
        foreach($worker->connections as $connection)
        {
            $connection->send(time().'========websocket');
        }
    }

    public function onWorkerReload($worker)
    {
        foreach($worker->connections as $connection)
        {
            $connection->send('websocket worker reloading');
        }
    }


}

在public下新建2个启动文件

public/worker_tcp.php

#!/usr/bin/env php
<?php
define('APP_PATH', __DIR__ . '/../application/');
define('BIND_MODULE','worker/Worker');
// 加载框架引导文件
require __DIR__ . '/../thinkphp/start.php';

public/worker_web.php

#!/usr/bin/env php
<?php
define('APP_PATH', __DIR__ . '/../application/');
define('BIND_MODULE','worker/Websecket');
// 加载框架引导文件
require __DIR__ . '/../thinkphp/start.php';

启动方法

在public目录下

启动tcp

php worker_tcp.php

启动websocket

php worker_web.php

不过写两个bat文件启动更方便:

php worker_tcp.php
php worker_web.php

完毕!!!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

炼气三千年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值