Question

I'm relatively new to php, but I can program in other languages (js, java, c/c++). I have a problem and I can't seem to be able to solve, so I'm hoping that someone can help me out here :)

I created a server_class.php file which manages connections between multiple clients. The clients connect to the php server via the web. When I launch the server_class.php it executes two applications (they are in an endless loop) and print data to the terminal. When a client connects to the php server, I want the server to start sending the output of each application to each client, so the clients can see the current output of each application. I have partially achieved this. However, it only sends the output of one application and not the other.

The function below is executed when the connection between the server and the client is performed:

private function startProc($client) {
    $this->output("Start a client process");
    $pid = pcntl_fork();
    if($pid == -1) {
        $this->output("fork terminated!");
    }
    elseif($pid) { // process
        $client->setPid($pid);
    }
    else {
        $this->output("Starting app1 data pipe...");
        exit($this->launchAppOneProc($client));

        $this->output("Starting app2 data pipe...");
        exit($this->launchAppTwoProc($client));
    }
}

Ok, once the connection between the client and the server is done, this function is executed. As you can see, I create a new process which then executes two methods: launchAppOneProc and launchAppTwoProc. These two functions contain the following code:

private function launchAppOneProc($client) {
    while (@ ob_end_flush()); // end all output buffers if any

    while (!feof($this->appone_proc))
    {   
        $appone_text = fread($this->appone_proc, 4096);
        $this->send($client, $appone_text);
        flush();
    }

    $this->output("AppOne has stopped running!");
}

The function above is the same as for launchAppTwoProc(). The function $this->output prints the text specified into the terminal of the server_class.php

So the problem is that it only executes launchAppOneProc() function and does not execute the next function launchAppTwoProc().

Any ideas on how I can execute both functions?

Thank you David

Was it helpful?

Solution

Ok, I found a solution to my problem. To clear some confusion, I have two applications that are running in the background and writing to a buffer. When a client connects to the server, they connect to both buffers and start receiving data. So what I did was to create a new process for each channel. When the client connects to the server, two processes are created and assigned to the client. Each process is connected to a buffer and starts sending data to the client.

private function startProc($client) {
    $this->output("Start a client process");

    for ($i = 0; $i < 2; ++$i) {
        // Create new process.
        $pid = pcntl_fork();

        switch ($pid) {
            case -1: // Failed to create new process.
                $this->output("Failed to create new process!");
                break;

            case 0: // Child process created, execute code...
                switch ($i) {
                    case 0:
                        $this->output("Connect to AppOne data pipe...");
                        $this->launchAppOneProc($client);
                        break;

                    case 1:
                        $this->output("Connect to AppTwo data pipe...");
                        $this->launchAppTwoProc($client);
                        break;
                }

            default: // Back to parent.
                switch ($i) {
                    case 0:
                        $client->setAppOnePid($pid);
                        break;
                    case 1:
                        $client->setAppTwoPid($pid);
                        break;
                }
        }
    }
}

I know I can use an array to store the process IDs, etc. But for now, this works. Once the client disconnects, each process for the client that just left has to be terminated as such:

posix_kill($client->getAppOnePid(), SIGTERM);
posix_kill($client->getAppTwoPid(), SIGTERM);

I hope this make sense and helps anyone who runs into the same problem.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top