Это серверная программа для веб-сокетов, когда клиент отправляет команду "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();
}
?>
Любая догадка, почему код в части редактирования работает там, где, когда он интегрирован в клиентское серверное приложение, его вывод не так, как ожидалось.
$child_proc = escapeshellcmd("unbuffer /var/www/html/test/websockets/./add")
ключевое слово unbuffer вызывало проблему, хотя она была там по какой-то другой причине, но это была одна проблема создания.
scanf("%d", &first);
оставляет новую строку в потокеstdin
в вашей программе на C ... Рассмотрите возможность очистки буфера перед повторным вызовомscanf
...