gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-30 17:34:08 25 4
gpt4 key购买 nike

这是一个服务器客户端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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com