Всем привет! Скажите пожалуйста, как можно в exe программу передавать и получать вывод из нее не закрывая саму программу. Пробовал через proc_open, но эта функция вроде как не может реализовать постоянное "общение" с нужной мне программой.
если программа работает с базовым вводом-выводом то как раз proc_open и потом fwrite и stream_get_contents (см ман по proc_open)
А можно ли после чтения, снова записать в тот же процесс без повторного запуска exe? В мануале не нашел.
Не получается, программа закрывается после записи команд, я могу только прочитать, ее вывод. И мне приходится постоянно ее заново запускать, хотя если работать вручную, через командную строку, то такого не происходит. Значит проблема в особенности функции proc_open? Добавлено спустя 3 минуты 12 секунд: Код (Text): <?php $time = microtime(1); $cwd='./'; $descriptorspec = array( 0 => array("pipe","r"), 1 => array("pipe","w"), ) ; // define current working directory where files would be stored $other_options = array('bypass_shell' => 'true'); // open process /bin/sh $process = proc_open('stockfish', $descriptorspec, $pipes, $cwd, null, $other_options) ; if (is_resource($process)) { // anatomy of $pipes: 0 => stdin, 1 => stdout, 2 => error log fwrite($pipes[0], "uci\n"); fwrite($pipes[0], "ucinewgame\n"); fwrite($pipes[0], "isready\n"); fwrite($pipes[0], "position startpos moves e2e4 e7e5 b1c3 b7b6 g1f3 c8b7 f3e5 d7d5 e4d5 b7d5 f1b5 e8e7 d2d4 c7c6 d1e2 c6b5\n"); fwrite($pipes[0], "go movetime 3000\n". PHP_EOL); //usleep(1000000); # задержка в 1 секунду, чтобы получить весь вывод. fclose($pipes[0]) ; // print pipe output echo stream_get_contents($pipes[1]) ; // close pipe fclose($pipes[1]) ; // all pipes must be closed before calling proc_close. // proc_close() to avoid deadlock proc_close($process) ; } echo microtime(1)-$time; ?>
не вижу тут бесконечного цикла раз. два - если работать через командную строку это как выглядит? спам командами или интерактивный режим. и три - где вот этот пхп-сценарий выполняется? через веб?
Ну бесконечный цикл здесь бессмыслен, т.к программа закрывается сразу, как я начинаю считывать результаты. Интерактивный режим (вручную вводил команды) Этот сценарий выполняется на моем компьютере.
я не буду глубоко разбираться с тем что это за программа. вот код который последовательно пишет команды в интерактивный шелл процесса и читает из него ответ Код (PHP): <?php $sf = '/home/ganzal/sf/stockfish-5-linux/Linux/stockfish_14053109_x64'; $time = microtime(1); $cwd='./'; $descriptorspec = array( 0 => array("pipe","r"), 1 => array("pipe","w"), ) ; $other_options = array('bypass_shell' => 'true'); // open process /bin/sh $process = proc_open($sf, $descriptorspec, $pipes, $cwd, null, $other_options) ; $cmds = array( "uci\n", "ucinewgame\n", "isready\n", #"position startpos moves e2e4 e7e5 b1c3 b7b6 g1f3 c8b7 f3e5 d7d5 e4d5 b7d5 f1b5 e8e7 d2d4 c7c6 d1e2 c6b5\n\n", "go movetime 3000\n" ); if (is_resource($process)) { stream_set_blocking($pipes[0], 0); while($cmd = array_shift($cmds)) { echo "\n < ", $cmd, "\n > "; fwrite($pipes[0], $cmd); fflush($pipes[0]); echo fread($pipes[1], 2048); } fclose($pipes[0]); echo stream_get_contents($pipes[1]); fclose($pipes[1]); proc_close($process) ; } echo microtime(1)-$time; # EOF вот вывод сценария: Код (Text): $ php test.php < uci > Stockfish 5 64 by Tord Romstad, Marco Costalba and Joona Kiiski < ucinewgame > id name Stockfish 5 64 id author Tord Romstad, Marco Costalba and Joona Kiiski option name Write Debug Log type check default false option name Write Search Log type check default false option name Search Log Filename type string default SearchLog.txt option name Book File type string default book.bin option name Best Book Move type check default false option name Contempt Factor type spin default 0 min -50 max 50 option name Mobility (Midgame) type spin default 100 min 0 max 200 option name Mobility (Endgame) type spin default 100 min 0 max 200 option name Pawn Structure (Midgame) type spin default 100 min 0 max 200 option name Pawn Structure (Endgame) type spin default 100 min 0 max 200 option name Passed Pawns (Midgame) type spin default 100 min 0 max 200 option name Passed Pawns (Endgame) type spin default 100 min 0 max 200 option name Space type spin default 100 min 0 max 200 option name Aggressiveness type spin default 100 min 0 max 200 option name Cowardice type spin default 100 min 0 max 200 option name Min Split Depth type spin default 0 min 0 max 12 option name Threads type spin default 1 min 1 max 128 option name Hash type spin default 32 min 1 max 16384 option name Clear Hash type button option name Ponder type check default true option name OwnBook type check default false option name MultiPV type spin default 1 min 1 max 500 option name Skill Level type spin default 20 min 0 max 20 option name Emergency Move Horizon type spin default 40 min 0 max 50 option name Emergency Base Time type spin default 60 min 0 max 30000 option name Emergency Move Time type spin default 30 min 0 max 5000 option name Minimum Thinking Time type spin default 20 min 0 max 5000 option name Slow Mover type spin default 80 min 10 max 1000 option name UCI_Chess960 type check default false uciok < isready > readyok < go movetime 3000 > info depth 1 seldepth 1 score cp 82 nodes 27 nps 1928 time 14 multipv 1 pv e2e4 info depth 2 seldepth 2 score cp 82 nodes 40 nps 2666 time 15 multipv 1 pv e2e4 info nodes 40 time 15 bestmove e2e4 ponder (none) 0.24574899673462 одну из команд закомментировал потому что на ней обмен зависал. но это вам должно быть более известно что не так с той строкой. идея такая: объявили массив команд. пока есть команды - пишем их во входной пайп и тут же читаем ответ от интерактивной консоли приложения. если вдруг перехватывать вывод (делать не echo fread() а $r = fread()) то можно обработать ответ и придумать новую команду которую запихнуть unshift-ом в начало очереди или pop-ом в конец. гуд лак, хэв фан.
Код (Text): <?php $time = microtime(1); $cwd='C:\WebServers\home\goodkis.ru\www\chess'; $descriptorspec = array( 0 => array("pipe","r"), 1 => array("pipe","w"), ) ; $other_options = array('bypass_shell' => 'true'); $process = proc_open('Strelka6.exe', $descriptorspec, $pipes, $cwd, null, $other_options) ; if (is_resource($process)) { fwrite($pipes[0], "uci\n"); fwrite($pipes[0], "ucinewgame\n"); fwrite($pipes[0], "isready\n"); fwrite($pipes[0], "position startpos moves e2e4 e7e5 b1c3 b7b6 g1f3 c8b7 f3e5 d7d5 e4d5 b7d5 f1b5 e8e7 d2d4 c7c6 d1e2 c6b5\n"); fwrite($pipes[0], "go movetime 1000\n". PHP_EOL); while(true){ usleep(500); $s = fgets($pipes[1],4096); $str .= $s; if(strpos(' '.$s,'bestmove')){ break; } } echo $s; fclose($pipes[0]); fclose($pipes[1]); proc_close($process); } echo microtime(1)-$time; ?> Этот код конечно не полностью показывает мою задумку. Можно сделать так, чтобы процесс висел в памяти и не запускался каждый раз, а также отправлять и считывать результат.Можно сделать вечный цикл, получать команды через файл, и записывать ответы в файл.