如何利用workerman充当ws客户端,然后动态的创建客户端数量

864328615

截图

如上图,我有个需求,就是我有个用户表,后台新增一个用户,就在workerman里为这个用户新建一个websocket链接,现在计划的是在进程启动时 先启动一个http端口,后台新增用户了就带着用户信息请求http服务,然后服务里根据传过来的用户信息为用户创建websocket链接,现在问题来了,怎么存储websocket的实例呢,搜到有人遇到同样的问题,看他是用$_SESSION,但是这个被作者说了不行

347 2 0
2个回答

walkor

弄个类,存储在静态变量里就行了

class MyConnections {
    public static connections = [];
}

存的时候

MyConnections::connection[标记] = $connection;

起始按照你截图的用法,存$connection没什么意义。

  • 暂无评论
864328615
class Worker extends Server
{
    protected $processes = 1;

    protected function init()
    {
        $ws = new \Workerman\Worker('websocket://0.0.0.0:2000');
        // 启动4个进程对外提供服务
        $ws->count = 1;
        $ws->onConnect = function (TcpConnection $connection){
        };

        $ws->onMessage = function (TcpConnection $connection,$data) {
            $connection->send('aaaa');
        };
        $ws->onClose = function (TcpConnection $connection) {
            var_dump('ws断开');
        };

        parent::init(); // TODO: Change the autogenerated stub
    }

    public static $i = 0;

    /**
     * http服务
     * @param $connection
     * @param $data
     */
    public function onMessage($connection, $data)
    {
        //pc管理后台新建用户会请求这个http服务,收到新注册用户消息,为用户创建ws链接
//        var_dump($data['get']['ws_url']);
        $con = new AsyncTcpConnection('ws://127.0.0.1:2000');

        //开始链接
        $con->onConnect = function ($con) {

        };

        //链接成功
        $con->onWebSocketConnect = function (AsyncTcpConnection $connection) {
            $connection->uid = ++ self::$i;
            //1更新用户在线状态

            //2启动心跳定时器
            $connection->timer_id = Timer::add(10, function () use($connection) {
                $ping = [
                    'msgId' => 122333,
                    'type'  => 'common.topic.clientheartbeat',
                    'msg'   => '',
                ];
                $connection->send(json_encode($ping, JSON_UNESCAPED_UNICODE));
            });
        };

        //收到消息
        $con->onMessage = function (AsyncTcpConnection $connection, $data) {
            var_dump($connection->uid.':收到消息');
//            $data = json_decode($data, true);
//            //服务端心跳
//            if ($data['heartbeat']) {
//                return;
//            }
//
//            $msgId = $data['msgId'];
//            switch ($data['type']) {
//                case 'authorize.topic.dismissnotify':
//                    echo '解除门店授权';
//
//                    break;
//                case 'product.topic.flowstatuschange':
//                    echo '商品状态变更';
//
//                    break;
//                default:
//                    break;
//            }
//
//            //回复
//            $ack = [
//                'msgId' => $msgId,
//                'type'  => '',
//                'msg'   => 'ack'
//            ];
//            $connection->send(json_encode($ack, JSON_UNESCAPED_UNICODE));
        };

        //链接关闭
        $con->onClose = function (AsyncTcpConnection $connection) {
            echo 'onClose' . PHP_EOL;
            //1删除心跳定时器
            if (isset($connection->timer_id)) {
                Timer::del($connection->timer_id);
            }
            //2更新用户下线状态
        };

        //链接失败
        $con->onError = function (AsyncTcpConnection $connection, $code, $msg) {
        };

        //链接
        $con->connect();
    }

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

    }

    /**
     * 当连接断开时触发的回调函数
     * @param $connection
     */
    public function onClose($connection)
    {

    }

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

    /**
     * 每个进程启动
     * @param $worker
     */
    public function onWorkerStart($worker)
    {

    }
}

截图
大佬我把代码修改成了这样 我发现客户同虽然每次都new 了 但是并没有影响到之前的链接,我开了ws服务根http服务,在http没请求一次就new AsyncTcpConnection,模拟了下我的需求,貌似这么写没啥问题,服务端能收到消息,动态新增的客户端也能收到消息。

  • 小W 2023-09-06

    uid应该是http请求携带的用户信息,不然可能创建无数个客户端

  • 小W 2023-09-06

    Event-Loop使用Event扩展

  • 864328615 2023-09-06

    不用那个扩展,没多少用户有100个就很厉害了,一个用户就是一个门店

🔝