php - 无法使用 PHP 创建的管道写入 C 应用程序的 STDIN

标签 php html c linux web

这是一个服务器客户端Web套接字程序,当客户端发送“exe”命令时,服务器执行一个C应用程序。 C 应用程序的输出由服务器从 STDOUT 读取并显示在客户端浏览器上。 现在有一个C应用程序需要用户输入(scanf),我们将输入保存在txt文件中。我们读取输入 并将其写入c程序的stdin。问题是 C 程序似乎不接受输入 我们在标准输入上写的。当我在没有任何流选择的情况下尝试此代码时,它正在工作并显示从输入文件读取的两个数字的总和,但是当我将其放入流选择命令中时,它会产生问题。我的完整服务器代码在最后。

根据客户端请求创建子进程的服务器代码的一部分

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

输入.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的过程有两个,我用proc open启动1。

完整的服务器代码

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

 ?>

有什么想法可以解决这个问题吗? 谢谢!

编辑

以下代码写入 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();
            }

    ?>

任何猜测为什么编辑部分中的代码都可以工作,但当集成到客户端服务器应用程序中时,其输出却不像预期的那样。

最佳答案

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

关键字 unbuffer 导致了问题,尽管它是由于其他原因而存在的,但它是造成问题的原因。

关于php - 无法使用 PHP 创建的管道写入 C 应用程序的 STDIN,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23488378/

相关文章:

html - 尝试使用 flexbox 在同一行显示两个无序列表

javascript - Vue v-bind 的工作原理

c - 使用 C 查找 JPG/JPEG 图像的高度和宽度

c++ - 直接将子句添加到 z3 求解器

php - DOCKER:运行gulp-php网站时出错

php - Magento 将自定义字段添加到客户帐户教程问题

JavaScript 不适用于隐藏和显示文本框

php - WordPress/Codeigniter 集成 - 将 WP 简码属性传递给 CI 脚本

javascript - 在循环中将参数传递给 jquery .load 回调函数

c - 如何使用 scanf - C 从日期中读取斜杠 (/)