workerman icon indicating copy to clipboard operation
workerman copied to clipboard

Workerman broadcast

Open Vitalicus opened this issue 2 years ago • 8 comments

My old code was like this

<?php
class SocketService
{
    private $connections;
    private $worker;
    public function run(){

        $context = array(
            'ssl'=>array(
            'local_cert'=>'/var/www/mysite.com/SSL/cert.pem',
            'local_pk'=>'/var/www/mysite.com/SSL/privkey.pem',
            'verify_peer'=>false,
            )
        );

        $this->worker = new \Workerman\Worker('websocket://mysite.com:888',$context);
        $this->worker->transport='ssl';
        $this->worker->count=40;
        $this->worker->onConnect = function($connection){
            $connection->onWebSocketConnect = function ($connection,$header){
            $this->connections[$_GET['userId']] = $connection;    
                dump(array_keys($this->connections));
            };
        };

        $this->worker->onMessage = function ($connection,$data) {
            dump(count($this->connections));
            foreach ($this->connections as $key => $connection) {
                dump('send message to user: ' . $key);
                $connection->send($data);
            }
        };
        \Workerman\Worker::runAll();
    }
}

In this version I can't get userID and send data to all users :(. Please help

Vitalicus avatar Apr 01 '23 09:04 Vitalicus

The v4 (and up) don't use superglobals ($_GET, $_POST, ...). Now uses a Request object, so to get the userID, you need to change $_GET['userId'] to Request->get('userID'). And pass the Request in the onConnect.

Before:

$this->worker->onConnect = function($connection){
            $connection->onWebSocketConnect = function ($connection,$header){
            $this->connections[$_GET['userId']] = $connection;    
                dump(array_keys($this->connections));
            };
        };

Now:

$this->worker->onConnect = function($connection, $request) {
            $connection->onWebSocketConnect = function ($connection, $header){
            $this->connections[$request->get(['userId')] = $connection;    
                dump(array_keys($this->connections));
            };
        };

Request methods:

    $request->get();
    $request->post();
    $request->header();
    $request->cookie();
    $request->session();
    $request->uri();
    $request->path();
    $request->method();

joanhey avatar Apr 01 '23 10:04 joanhey

@joanhey Does v5 support superglobals? How does same superglobal keep in same async callback context? I mean superglobal cross the whole process, but multiple async callback running sametime in one process.

xpader avatar Apr 12 '23 14:04 xpader

Workerman v4 and v5 don't use superglobals. Because some event systems, use threads, and it's NOT possible use it with superglobals.

But you can use Adapterman: https://github.com/joanhey/AdapterMan that always will work with superglobals, with the event systems that permit it. (event php, event lib, ev, ...)

joanhey avatar Apr 12 '23 15:04 joanhey

Hello @joanhey, but $this->worker->onConnect to websockets don't include the second parameter $request, you only get the first one $connection, no?

eusonlito avatar Apr 13 '23 22:04 eusonlito

@joanhey Tell me please, how to do foreach. Send recived data for each client

Vitalicus avatar Apr 14 '23 06:04 Vitalicus

Workerman V5

<?php
class SocketService
{
    private $connections;
    private $worker;
    public function run(){

        $context = array(
            'ssl'=>array(
            'local_cert'=>'/var/www/mysite.com/SSL/cert.pem',
            'local_pk'=>'/var/www/mysite.com/SSL/privkey.pem',
            'verify_peer'=>false,
            )
        );

        $this->worker = new \Workerman\Worker('websocket://mysite.com:888',$context);
        $this->worker->transport='ssl';
        // Do not use multiple processes as connections cannot be shared between processes
        $this->worker->count=1; 
        $this->worker->onConnect = function($connection){
            $connection->onWebSocketConnect = function ($connection, $request){
                $this->connections[$request->get('userId')] = $connection;    
                dump(array_keys($this->connections));
            };
        };

        $this->worker->onMessage = function ($connection,$data) {
            dump(count($this->connections));
            foreach ($this->connections as $key => $connection) {
                dump('send message to user: ' . $key);
                $connection->send($data);
            }
        };
        \Workerman\Worker::runAll();
    }
}

walkor avatar Apr 14 '23 07:04 walkor

@walkor Hi!

  1. Is there a possability to use your example, but with multiple processes (if there is any, can you share)? Or i doomed to use only one process if i wanna make it work within class?
  2. Will i be able to get connections inside another method in the class? I wanna use SSE within class, so basically i need some another methods inside.
  3. Is Workerman v5 required for this or v4 is enough?

shizzic avatar Aug 01 '23 13:08 shizzic

  1. No
  2. No
  3. v4 is enough

A single process of Workerman is capable of handling over 10,000 connections, which is sufficient for the majority of business needs.

Here is an example for multiple processes broadcast. https://www.workerman.net/doc/workerman/components/channel-examples2.html

And this is an example for multiple server and processes broadcast. https://www.workerman.net/doc/workerman/components/channel-examples.html

walkor avatar Aug 02 '23 09:08 walkor