Невозможно записать в STDIN приложения C, используя каналы, созданные в PHP

0

Это серверная программа для веб-сокетов, когда клиент отправляет команду "exe", сервер выполняет приложение C. Вывод приложения c считывается из STDOUT сервером и отображается в браузере клиента. Теперь есть приложение C, которое требует ввода пользователя (scanf), мы сохранили вход в txt файл. Мы читаем ввод и записываем его в stdin программы c. Проблема в том, что кажется, что программа на C не принимает ввод, который мы пишем на stdin. Когда я пробовал этот код без выбора потока, он работал и отображал сумму двух чисел, считанных из входного файла, но когда я помещаю его в поток, выберите команду его создание проблемы. Полный код сервера завершен.

часть кода сервера, которая создает дочерний процесс по запросу клиента

if(strcmp($user_message, "exe") == 0 ) {
     echo "Executing a process\n";
     $cwd = '/var/www/html/test/websockets' ;

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

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

         $read_socks[] = $pipes[1];//add a descriptor 
         $stdout = array($pipes[1]);//save stdout in a variable defined above
         $stdin  = array($pipes[0]);

         print_r ($stdout); 
         print_r ($stdin);
      } 
     }
     else
     {
       echo "Passing value to the C program".$user_message;

       //Read input.txt by line and store it in an array
       $input = array(); 
       $input = file('/var/www/html/test/websockets/input.txt');

     echo "INPUT";
     print_r($input);
     echo "\n";

     //Feed the input (hardcoded)
     $bytes = fwrite($stdin[0], "$input[0] $input[1]");
     echo "Bytes written:".$bytes;
                 sleep(1);

             }
     }      
} 

add.c

#include <stdio.h>

int main(void)
{
      int first, second;

      printf("Enter two integers > \n");
      scanf("%d", &first);
      scanf("%d", &second);
      printf("The two numbers are: %d  %d\n", first, second);
      printf("Output: %d\n", first+second);
}

input.txt

2
4   

вывод

Passing value to the C program3Array
(
    [0] => Resource id #11
)

INPUTArray
(
    [0] => 2

    [1] => 4

)

Bytes written:5

Выполняя ps, я получаю

root      1173  1164  0 12:08 pts/6    00:00:00 tclsh /usr/bin/unbuffer /var/www/html/test/websockets/./add
root      1174  1173  0 12:08 pts/8    00:00:00 /var/www/html/test/websockets/./add

После того, как байты, написанные сервером, висят, нет ответа от приложения C, т.е. результат добавления 4 + 2. Почему есть два процесса add я start 1 с proc open.

полный код сервера

     <?php
    execute_prog('unbuffer /var/www/html/test/websockets/./add');//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 

            );

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

//       if (is_resource($process))
          {
              $client_socks = array();
                      $read_socks = array($server);
                      $changed = array();
                      $stdout = NULL; 
                      $stdin = NULL; 

            while(1)
            {
                //prepare readable sockets
                $write  = NULL; 
                $err    = NULL;
                $except = NULL;
                            $changed = $read_socks;//by refrence
/*
                            echo "stdout:";
                            print_r ($stdout);
                echo "\n";

                echo "changed:";
                print_r ($changed);
                echo "\n";

                echo "read sock:";
                print_r ($read_socks);
                echo "\n";
*/
                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>";

                             //prepare data to be sent to client
                             $response_text = mask(json_encode(array('type'=>'usermsg', 'name'=>$user_name, 'message'=>$s, 'color'=>$user_color)));
                                                 foreach ($read_socks as $sock)
                                                     {  
                                                       if(($sock != $server) && ($sock != $stdout))
                                               fwrite($sock, $response_text, strlen($response_text));
                                                     }

                             $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));
//..................................................................................................................

                                                             if(strcmp($user_message, "exe") == 0 )
                                                             {
                                     echo "Executing a process\n";
                                     $cwd = '/var/www/html/test/websockets' ;

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

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

                                         $read_socks[] = $pipes[1];//add a descriptor 
                                         $stdout = array($pipes[1]);//save stdout in a variable defined above
                                                                             $stdin  = array($pipes[0]);

                                         print_r ($stdout); 
                                                                             print_r ($stdin);
                                      } 
                                                             }
                                                             else
                                                             {
                                                                 echo "Passing value to the C program".$user_message;
                                                                 print_r ($stdin);
                                     echo "\n";
                                                                 //$input = array($user_message);
                                    // fwrite($stdin[0],"$input[0]");//,strlen($user_message));   

                                     //Read input.txt by line and store it in an array
                                                                 $input = array(); 
                                     $input = file('/var/www/html/test/websockets/input.txt');
                                                                 echo "INPUT";
                                                                 print_r($input);
                                                                 echo "\n";

                                     //Feed the input (hardcoded)
                                     $bytes = fwrite($stdin[0], "$input[0] $input[1]");// $input[1]");
                                     echo "Bytes written:".$bytes;

                                                             }
                                                     }      
                         } 
                                     }

                    $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;
}

 ?>

Есть идеи, как это решить? Спасибо!

РЕДАКТИРОВАТЬ

Следующий код записывается в stdin приложения C, но когда я попытался интегрироваться на вышеуказанный клиентский сервер, он не работает.

 <?php
 //descriptors to be handled by parent
 $descriptorspec = array(
        0 => array("pipe", "r"),
        1 => array("pipe", "w"),
        2 => array("file", "/var/www/html/websockets/error.txt", "a")
    );

    // define current working directory where files would be stored
    $cwd = '/var/www/html' ;

    $child_proc = escapeshellcmd("unbuffer /var/www/html/test/websockets/./add");
   // $process = proc_open('/var/www/html/websockets/add', $descriptorspec, $pipes);//creating child process
    $process = proc_open($child_proc, $descriptorspec, $pipes, $cwd);//creating child process
    sleep(1);

    if (is_resource($process))
    {

            //Read input.txt by line and store it in an array
            $input = file('/var/www/html/test/websockets/input.txt');

            //Feed the input (hardcoded)
            fwrite($pipes[0], "$input[0] $input[1]");

            fclose($pipes[0]);

            while ($s = fgets($pipes[1]))
            {
                print $s."</br>";
                flush();
            }

    ?>

Любая догадка, почему код в части редактирования работает там, где, когда он интегрирован в клиентское серверное приложение, его вывод не так, как ожидалось.

  • 0
    Я не знаю, приходило ли вам в голову, что scanf("%d", &first); оставляет новую строку в потоке stdin в вашей программе на C ... Рассмотрите возможность очистки буфера перед повторным вызовом scanf ...
  • 0
    @Elias Van Ootegem Я добавил fflush (stdin) между двумя программами scanf из C, но он не работает. Кажется, что программа на C не получает ввод от stdin, я даже пытался ввести add newline, т.е. fwrite ($ stdin [0], "$ input [0] \ n $ input [1] \ n"), но это также не работает.
Показать ещё 4 комментария
Теги:
web

1 ответ

0
 $child_proc = escapeshellcmd("unbuffer /var/www/html/test/websockets/./add")

ключевое слово unbuffer вызывало проблему, хотя она была там по какой-то другой причине, но это была одна проблема создания.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню