За последние 24 часа нас посетили 17705 программистов и 1710 роботов. Сейчас ищут 928 программистов ...

proc_open

Тема в разделе "Прочие вопросы по PHP", создана пользователем tparser, 15 окт 2014.

  1. tparser

    tparser Новичок

    С нами с:
    15 окт 2014
    Сообщения:
    6
    Симпатии:
    0
    Всем привет! Скажите пожалуйста, как можно в exe программу передавать и получать вывод из нее не закрывая саму программу. Пробовал через proc_open, но эта функция вроде как не может реализовать постоянное "общение" с нужной мне программой.
     
  2. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    если программа работает с базовым вводом-выводом то как раз proc_open и потом fwrite и stream_get_contents (см ман по proc_open)
     
  3. tparser

    tparser Новичок

    С нами с:
    15 окт 2014
    Сообщения:
    6
    Симпатии:
    0
    А можно ли после чтения, снова записать в тот же процесс без повторного запуска exe? В мануале не нашел.
     
  4. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    если программа это поддерживает - да. просто в (бесконечном) цикле выполняйте запись-чтение
     
  5. tparser

    tparser Новичок

    С нами с:
    15 окт 2014
    Сообщения:
    6
    Симпатии:
    0
    Не получается, программа закрывается после записи команд, я могу только прочитать, ее вывод. И мне приходится постоянно ее заново запускать, хотя если работать вручную, через командную строку, то такого не происходит. Значит проблема в особенности функции proc_open?

    Добавлено спустя 3 минуты 12 секунд:
    Код (Text):
    1. <?php
    2.  
    3. $time = microtime(1);
    4. $cwd='./';
    5.  
    6. $descriptorspec = array(
    7. 0 => array("pipe","r"),
    8. 1 => array("pipe","w"),
    9. ) ;
    10.  
    11. // define current working directory where files would be stored
    12.  
    13. $other_options = array('bypass_shell' => 'true');
    14.  
    15. // open process /bin/sh
    16. $process = proc_open('stockfish', $descriptorspec, $pipes, $cwd, null, $other_options) ;
    17.  
    18. if (is_resource($process)) {
    19.  
    20.   // anatomy of $pipes: 0 => stdin, 1 => stdout, 2 => error log
    21.   fwrite($pipes[0], "uci\n");
    22.   fwrite($pipes[0], "ucinewgame\n");
    23.   fwrite($pipes[0], "isready\n");
    24.  
    25.   fwrite($pipes[0], "position startpos moves e2e4 e7e5 b1c3 b7b6 g1f3 c8b7 f3e5 d7d5 e4d5 b7d5 f1b5 e8e7 d2d4 c7c6 d1e2 c6b5\n");
    26.   fwrite($pipes[0], "go movetime 3000\n". PHP_EOL);
    27.   //usleep(1000000); # задержка в 1 секунду, чтобы получить весь вывод.
    28.  
    29.   fclose($pipes[0]) ;
    30.  
    31.   // print pipe output
    32.  
    33.   echo stream_get_contents($pipes[1]) ;
    34.  
    35.   // close pipe
    36.   fclose($pipes[1]) ;
    37.  
    38.   // all pipes must be closed before calling proc_close.
    39.   // proc_close() to avoid deadlock
    40.   proc_close($process) ;
    41. }
    42.  
    43. echo microtime(1)-$time;
    44.  
    45. ?>
     
  6. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    не вижу тут бесконечного цикла раз. два - если работать через командную строку это как выглядит? спам командами или интерактивный режим. и три - где вот этот пхп-сценарий выполняется? через веб?
     
  7. tparser

    tparser Новичок

    С нами с:
    15 окт 2014
    Сообщения:
    6
    Симпатии:
    0
    Ну бесконечный цикл здесь бессмыслен, т.к программа закрывается сразу, как я начинаю считывать результаты. Интерактивный режим (вручную вводил команды) Этот сценарий выполняется на моем компьютере.
     
  8. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    я не буду глубоко разбираться с тем что это за программа. вот код который последовательно пишет команды в интерактивный шелл процесса и читает из него ответ
    Код (PHP):
    1. <?php
    2. $sf = '/home/ganzal/sf/stockfish-5-linux/Linux/stockfish_14053109_x64';
    3.  
    4. $time = microtime(1);
    5. $cwd='./';
    6.  
    7. $descriptorspec = array(
    8.     0 => array("pipe","r"),
    9.     1 => array("pipe","w"),
    10. ) ;
    11.  
    12. $other_options = array('bypass_shell' => 'true');
    13.  
    14. // open process /bin/sh
    15. $process = proc_open($sf, $descriptorspec, $pipes, $cwd, null, $other_options) ;
    16.  
    17. $cmds = array(
    18.     "uci\n",
    19.     "ucinewgame\n",
    20.     "isready\n",
    21.     #"position startpos moves e2e4 e7e5 b1c3 b7b6 g1f3 c8b7 f3e5 d7d5 e4d5 b7d5 f1b5 e8e7 d2d4 c7c6 d1e2 c6b5\n\n",
    22.     "go movetime 3000\n"
    23. );
    24.  
    25.  
    26. if (is_resource($process)) {
    27.     stream_set_blocking($pipes[0], 0);
    28.     
    29.     while($cmd = array_shift($cmds)) {
    30.         echo "\n < ", $cmd, "\n > ";
    31.         
    32.         fwrite($pipes[0], $cmd); fflush($pipes[0]);
    33.         
    34.         echo fread($pipes[1], 2048);
    35.     }
    36.     
    37.     fclose($pipes[0]);
    38.     
    39.     echo stream_get_contents($pipes[1]);
    40.     
    41.     fclose($pipes[1]);
    42.     
    43.     proc_close($process) ;
    44. }
    45.  
    46. echo microtime(1)-$time;
    47.  
    48. # EOF  
    вот вывод сценария:
    Код (Text):
    1.  $ php test.php
    2.  
    3.  < uci
    4.  
    5.  > Stockfish 5 64 by Tord Romstad, Marco Costalba and Joona Kiiski
    6.  
    7.  < ucinewgame
    8.  
    9.  > id name Stockfish 5 64
    10. id author Tord Romstad, Marco Costalba and Joona Kiiski
    11.  
    12. option name Write Debug Log type check default false
    13. option name Write Search Log type check default false
    14. option name Search Log Filename type string default SearchLog.txt
    15. option name Book File type string default book.bin
    16. option name Best Book Move type check default false
    17. option name Contempt Factor type spin default 0 min -50 max 50
    18. option name Mobility (Midgame) type spin default 100 min 0 max 200
    19. option name Mobility (Endgame) type spin default 100 min 0 max 200
    20. option name Pawn Structure (Midgame) type spin default 100 min 0 max 200
    21. option name Pawn Structure (Endgame) type spin default 100 min 0 max 200
    22. option name Passed Pawns (Midgame) type spin default 100 min 0 max 200
    23. option name Passed Pawns (Endgame) type spin default 100 min 0 max 200
    24. option name Space type spin default 100 min 0 max 200
    25. option name Aggressiveness type spin default 100 min 0 max 200
    26. option name Cowardice type spin default 100 min 0 max 200
    27. option name Min Split Depth type spin default 0 min 0 max 12
    28. option name Threads type spin default 1 min 1 max 128
    29. option name Hash type spin default 32 min 1 max 16384
    30. option name Clear Hash type button
    31. option name Ponder type check default true
    32. option name OwnBook type check default false
    33. option name MultiPV type spin default 1 min 1 max 500
    34. option name Skill Level type spin default 20 min 0 max 20
    35. option name Emergency Move Horizon type spin default 40 min 0 max 50
    36. option name Emergency Base Time type spin default 60 min 0 max 30000
    37. option name Emergency Move Time type spin default 30 min 0 max 5000
    38. option name Minimum Thinking Time type spin default 20 min 0 max 5000
    39. option name Slow Mover type spin default 80 min 10 max 1000
    40. option name UCI_Chess960 type check default false
    41. uciok
    42.  
    43.  < isready
    44.  
    45.  > readyok
    46.  
    47.  < go movetime 3000
    48.  
    49.  > info depth 1 seldepth 1 score cp 82 nodes 27 nps 1928 time 14 multipv 1 pv e2e4
    50. info depth 2 seldepth 2 score cp 82 nodes 40 nps 2666 time 15 multipv 1 pv e2e4
    51. info nodes 40 time 15
    52. bestmove e2e4 ponder (none)
    53. 0.24574899673462
    одну из команд закомментировал потому что на ней обмен зависал. но это вам должно быть более известно что не так с той строкой.
    идея такая: объявили массив команд. пока есть команды - пишем их во входной пайп и тут же читаем ответ от интерактивной консоли приложения. если вдруг перехватывать вывод (делать не echo fread() а $r = fread()) то можно обработать ответ и придумать новую команду которую запихнуть unshift-ом в начало очереди или pop-ом в конец. гуд лак, хэв фан.
     
  9. tparser

    tparser Новичок

    С нами с:
    15 окт 2014
    Сообщения:
    6
    Симпатии:
    0
    Спасибо, но я уже сделал своим способом.
     
  10. mahmuzar

    mahmuzar Старожил

    С нами с:
    6 апр 2012
    Сообщения:
    4.631
    Симпатии:
    425
    Адрес:
    РД, г. Махачкала.
    покажите свой способ
     
  11. tparser

    tparser Новичок

    С нами с:
    15 окт 2014
    Сообщения:
    6
    Симпатии:
    0
    Код (Text):
    1. <?php
    2.  
    3. $time = microtime(1);
    4. $cwd='C:\WebServers\home\goodkis.ru\www\chess';
    5.  
    6. $descriptorspec = array(
    7. 0 => array("pipe","r"),
    8. 1 => array("pipe","w"),
    9. ) ;
    10.  
    11. $other_options = array('bypass_shell' => 'true');
    12.  
    13. $process = proc_open('Strelka6.exe', $descriptorspec, $pipes, $cwd, null, $other_options) ;
    14.  
    15. if (is_resource($process)) {
    16. fwrite($pipes[0], "uci\n");
    17. fwrite($pipes[0], "ucinewgame\n");
    18. fwrite($pipes[0], "isready\n");
    19.  
    20. fwrite($pipes[0], "position startpos moves e2e4 e7e5 b1c3 b7b6 g1f3 c8b7 f3e5 d7d5 e4d5 b7d5 f1b5 e8e7 d2d4 c7c6 d1e2 c6b5\n");
    21. fwrite($pipes[0], "go movetime 1000\n". PHP_EOL);
    22.  
    23.  
    24. while(true){
    25. usleep(500);
    26. $s = fgets($pipes[1],4096);
    27. $str .= $s;
    28. if(strpos(' '.$s,'bestmove')){
    29. break;
    30. }
    31. }
    32.  
    33. echo $s;
    34.  
    35. fclose($pipes[0]);
    36. fclose($pipes[1]);
    37. proc_close($process);
    38.  
    39. }
    40.  
    41. echo microtime(1)-$time;
    42.  
    43. ?>
    Этот код конечно не полностью показывает мою задумку. Можно сделать так, чтобы процесс висел в памяти и не запускался каждый раз, а также отправлять и считывать результат.Можно сделать вечный цикл, получать команды через файл, и записывать ответы в файл.