Search code examples
phpsocketssoappipeline

Call a PHP instance method with another PHP file in system memory


I have a PHP socket server script named server.php that binding to a certain port and keep running for a long time. (actually it start in cli (terminal) mode and not will stop until ctrl+c command pressed.) Also there is a Soap-server PHP file named service.php that manage chat requests. (for example open a new room, accept or kick clients and so on.) Both two scripts access to a common database, so they can shared information.

But sometime it's necessary for SoapServer to call some methods of SocketServer (that it's running in system memory) asynchronously and get related data.

I'm looking for a simple and certain way to handle that. thanx for any tips.


Solution

  • Based on the little information I think your best bet is to ensure server.php does only one thing: opening a socket (e.g. on port 8001) and serve. It shouldn't contain any methods at all.

    You put your methods in another script, let's call it handler.php. In server.php you include it: require_once("handler.php");

    Nothing stops you from opening another socket on another port (e.g. 8002) that does not handle persistent connections, but instead responds to regular web requests. Call it server2.php for example. This server2.php also contains: require_once("handler.php");

    Then the SoapServer can use curl to make async requests to port 8002 and have access to the same methods that server.php uses for the persistent connection(s).

    A websocket that listens to regular ajax / web requests could look something like the code below. In my case handler.php has a method handle() that handles the $rawInput based on the $query. The $query could be as simple as the name of the method you want to invoke.

    ob_end_clean();
    header("Connection: close");
    ob_start();
    $size = ob_get_length();
    header("Content-Length: $size");
    ob_end_flush();
    flush();
    set_time_limit(0);
    require_once("handler.php");
    $sock = socket_create(AF_INET, SOCK_STREAM, 0);
    socket_bind($sock, "127.0.0.1" , 8002);
    socket_listen($sock, 1024);  
    
    while (true) {  
        $client   = socket_accept($sock); 
        $rawInput = socket_read($client, 204800);
        $input    = explode("\r\n", $rawInput); 
        $input    = explode(" ", $input[0]);
        $query    = isset($input[1]) ? $input[1] : '/';     
        $result   = handle($query, $rawInput);
        $headers  = "HTTP/1.0 200 OK\r\n";
        $headers .= "Connection: keep-alive\r\n";
        $headers .= "Content-Type: application/json\r\n";
        $headers .= "Content-Length: " . sprintf('%u', strlen($result)) . "\r\n";
        $headers .= "Keep-Alive: timeout=5, max=100\r\n";
        $output   = $headers . "\r\n" . $result;
    
        socket_write($client, $output, strlen($output));
        socket_shutdown($client, 1);
        socket_close($client);
    }
    
    socket_shutdown($sock);
    socket_close($sock);
    

    This example is taken from some code that I wrote and I'm actively using, removing the lines of code that are specific to my application. I hope it works for you too..

    Because the information provided was minimal - I don't know why you can't just let Apache have access to handler.php as well. But if it needs to be a websocket, above example could do the job.