Can't monitor STDOUT of a C program in parallel with web sockets, by using stream select in PHP

StackOverflow https://stackoverflow.com/questions/23466652

سؤال

I m writing a websocket based client server in PHP.Server is listeninig for clients which get connected from a browser, when client write something its echoed back to the client. Client input and new connection from the client are monitored by using stream select. In my previous work I used stream select to get output of the C program and display it on the browser now I want that when a client send some message I execute a C program using proc open. C program outputs "hello" message in a loop after certain time, I want that when ever there is output on the C program I send it to the client browser.

Client browser successful gets connected, when client sends data the server echo it back, the C program gets executed on server but I cant monitor its STDOUT by using same stream select that is monitoring my sockets.

I am not able to monitor my child process STDOUT using stream select. By using select How can I monitor the new process STDOUT that I started using proc open ,It looks that some how I lost the STDOUT descriptor that is usually accessible after starting the C program by using proc open.

hello.c

#include<stdio.h>
#include<stdint.h>

void main(void)
{
    uint8_t i = 0;
    uint8_t count = 10;

    for(i = 0; i < count; i++)
     {
    printf("hello world\n");
    sleep(1);
     }
 }

server.php

 execute_prog('unbuffer /var/www/html/test/./hello3');//unbuffer stdout

 function execute_prog($exe)
{
    echo "[+execute_prog]";

    $host = 'localhost'; //host
    $port = '9000'; //port
    $null = NULL; //null var
            $read_socks;
            $new_client;


    $server = stream_socket_server("tcp://0.0.0.0:9000", $errno, $errorMessage);

    if ($server === false)
    {
        throw new UnexpectedValueException("Could not bind to socket: $errorMessage");
    }

    set_time_limit(1800);

        $exe_command = escapeshellcmd($exe);

    $descriptorspec = array(

            0 => array("pipe", "r"),  // stdin -> for execution

            1 => array("pipe", "w"),  // stdout -> for execution

            2 => array("pipe", "w") // stderr 

        );


      {
          $client_socks = array();
                      $read_socks = array($server);
                      $changed = array();
                      $stdout = NULL;

            while(1)
        {
            //prepare readable sockets
            $write  = NULL; 
            $err    = NULL;
            $except = NULL;
                            $changed = $read_socks;//by refrence

            if (false === ($num_changed_streams = stream_select($changed, $write, $except, 0)))
            {
                /* Error handling */
                                echo "Errors\n";
            } 
            else if ($num_changed_streams > 0)
            {
                    /* At least on one of the streams something interesting happened */
                        echo "Data on ".$num_changed_streams." descriptor\n";

                                 if(in_array($stdout[0], $changed))
                 {
                     echo "Data on child process STDOUT\n";

                             $s = fgets($stdout[0]);

                     if( $s === false )
                                             {
                         // Hello program has finished.
                         echo 'Finished', PHP_EOL;

                         $s = NULL;
                         ob_flush();
                         flush();

                         // Close all descriptors and return...
                                                    // break;
                     }
                     else
                     {
                         echo $s."</br>";
                                         //fwrite($new_client,$s,strlen($s));//commented temporarily
                         $s = NULL;
                         ob_flush();
                         flush();
                     }

                 }
                                     else if(in_array($server, $changed))
                 {
                   //new client
                                       echo "New Connection\n";
                   $new_client = stream_socket_accept($server);

                   if ($new_client)
                   {
                       //print remote client information, ip and port number
                       echo 'Connection accepted from ' . stream_socket_get_name($new_client, true) . "n";
                              $read_socks[] = $new_client;
                      echo "Now there are total ". count($read_socks) . " clients.n";
                   }

                                       $header = fread($new_client, 1024);//read data sent by the socket
                   perform_handshaking($header, $new_client, $host, $port); //perform websocket handshake

                   $ip = stream_socket_get_name($new_client, true);
                   $response = mask(json_encode(array('type'=>'system', 'message'=>$ip.' connected'))); //prepare json data
                                   fwrite($new_client,$response,strlen($response));

                   //delete the server socket from the read sockets
                   unset($changed[ array_search($server, $changed) ]);

                                     }
                 else if($write)
                 {
                     echo "Data on child process STDIN\n";

                 }
                 else if($err)
                 {
                     echo "Data on child process STDERR\n";

                 }
                                     else
                 {
                                             echo "Message from the client \n";
                     //message from existing client

                     foreach($changed as $sock)
                     {
                         $data = fread($sock, 128);
                                                     //echo "Data read:".$data." From sock:".$sock."\n"; 
                         if(!$data)
                         {
                             unset($client_socks[ array_search($sock, $client_socks) ]);
                             @fclose($sock);
                             echo "A client disconnected. Now there are total ". count($client_socks) . " clients.n";
                             continue;
                         }
                                                     else
                         {
                             $received_text = unmask($data); //unmask data
                             $tst_msg = json_decode($received_text); //json decode 
                             $user_name = $tst_msg->name; //sender name
                             $user_message = $tst_msg->message; //message text
                             $user_color = $tst_msg->color; //color
                                                       //      echo "name:".$user_name." user mesg:".$user_message."\n";

                             //prepare data to be sent to client
                             $response_text = mask(json_encode(array('type'=>'usermsg', 'name'=>$user_name, 'message'=>$user_message, 'color'=>$user_color)));

                             fwrite($sock, $response_text, strlen($response_text));
   //..................................................................................................................

                             echo "Executing a process\n";

                             $process = proc_open($exe_command, $descriptorspec, $pipes);//creating child process

    if (is_resource($process))                                                         
                                                             {                              
                                                                echo "Process Created";     
                                                             }       





                             $read_sock[] = $pipes[1];//add a descriptor 
                                                             $stdout = array($pipes[1]);//save stdout in a variable defined above
                                                             print_r ($stdout); 
                                                     }  
                     } 
                                     }

                $num_changed_streams = 0;
            }


        }
                    // close the listening socket
                    fclose($server);
        fclose($pipes[0]);
        fclose($pipes[1]);
        fclose($pipes[2]);
        echo "exitcode: ".proc_close($process)."\n";
    }   


echo "[-execute_prog]";
  //    return $ret;
  }

Output Of server.php

    [+execute_prog]Data on 1 descriptor
    New Connection
    Connection accepted from 127.0.0.1:49875nNow there are total 2 clients.nData on 1     descriptor
    Message from the client 
    Executing a process
    Process Created Array
    (
        [0] => Resource id #12
    )

As can be seen from output that it never show message "Data on child process STDOUT" even the C program was created

Other utility functions unmask, mask etc can be provided if required.

Thankyou

هل كانت مفيدة؟

المحلول

i was saving the stdout in read_sock instead of read_socks array, now its resolved

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top