swoole-src icon indicating copy to clipboard operation
swoole-src copied to clipboard

Example script in swoole github is broken. How can the proxy server script be updated?

Open AlwaysCompile opened this issue 2 years ago • 2 comments

Please answer these questions before submitting your issue.

  1. What did you do? If possible, provide a simple script for reproducing the error.

The example script is broken: https://github.com/swoole/proxy-server/blob/master/tcp-proxy.php

  1. What did you expect to see?

The working script

  1. What did you see instead?

It is broken because swoole no longer supports callbacks for clients? The "on()" method cannot be found. Swoole also does not seem to provide a way to pipe data and events between sockets, so there is not a way to get data and relay it back to the client as a proxy server should do.

How can the example script be made working again with the new coroutine system?

AlwaysCompile avatar Nov 04 '23 00:11 AlwaysCompile

<?php
class ProxyServer
{
    protected $frontends;
    protected $backends;
    /**
     * @var swoole_server
     */
    protected $serv;
    protected $index = 0;
    protected $mode = SWOOLE_BASE;
    protected $backendServer = array('host' => '127.0.0.1', 'port' => '80');

    function run()
    {
        $serv = new Swoole\Server("127.0.0.1", 9509, $this->mode);
        $serv->set(array(
            'worker_num' => 8, //worker process num
            //'backlog' => 128, //listen backlog
            //'open_tcp_keepalive' => 1,
            //'log_file' => '/tmp/swoole.log', //swoole error log
        ));
        $serv->on('WorkerStart', array($this, 'onStart'));
        $serv->on('Receive', array($this, 'onReceive'));
        $serv->on('Close', array($this, 'onClose'));
        $serv->on('WorkerStop', array($this, 'onShutdown'));
        $serv->start();
    }

    function onStart($serv)
    {
        $this->serv = $serv;
        echo "Server: start.Swoole version is [" . SWOOLE_VERSION . "]\n";
    }

    function onShutdown($serv)
    {
        echo "Server: onShutdown\n";
    }

    function onClose($serv, $fd, $from_id)
    {
        if (isset($this->frontends[$fd]))
        {
            $backend_socket = $this->frontends[$fd];
            $backend_socket->closing = true;
            $backend_socket->close();
            unset($this->backends[$backend_socket->sock]);
            unset($this->frontends[$fd]);
        }
        echo "onClose: frontend[$fd]\n";
    }

    function onReceive($serv, $fd, $from_id, $data)
    {
        if (!isset($this->frontends[$fd]))
        {
            $socket = new swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_ASYNC);
            $socket->closing = false;
            $socket->on('connect', function (swoole_client $socket) use ($data)
            {
                $socket->send($data);
            });

            $socket->on('error', function (swoole_client $socket) use ($fd)
            {
                echo "ERROR: connect to backend server failed\n";
                $this->serv->send($fd, "backend server not connected. please try reconnect.");
                $this->serv->close($fd);
            });

            $socket->on('close', function (swoole_client $socket) use ($fd)
            {
                echo "onClose: backend[{$socket->sock}]\n";
                unset($this->backends[$socket->sock]);
                unset($this->frontends[$fd]);
                if (!$socket->closing)
                {
                    $this->serv->close($fd);
                }
            });

            $socket->on('receive', function (swoole_client $socket, $_data) use ($fd)
            {
                $this->serv->send($fd, $_data);
            });

            if ($socket->connect($this->backendServer['host'], $this->backendServer['port']))
            {
                $this->backends[$socket->sock] = $fd;
                $this->frontends[$fd] = $socket;
            }
            else
            {
                echo "ERROR: cannot connect to backend server.\n";
                $this->serv->send($fd, "backend server not connected. please try reconnect.");
                $this->serv->close($fd);
            }
        }
        else
        {
            /**
             * @var $socket swoole_client
             */
            $socket = $this->frontends[$fd];
            $socket->send($data);
        }
    }
}

$serv = new ProxyServer();
$serv->run();

NathanFreeman avatar Nov 04 '23 10:11 NathanFreeman

Hello @NathanFreeman that is still using the same broken script. Swoole no longer supports clients with SWOOLE_SOCK_ASYNC. You can see this here: https://github.com/swoole/ext-async

Does swoole no longer support this functionality in the latest versions or is there a way to perform the proxy using supported methods? It looks like swoole has removed async client support and only supports coroutines. Can routines be used to make the proxy script work as intended?

AlwaysCompile avatar Nov 04 '23 18:11 AlwaysCompile