2010-07-31 59 views
0

我正在嘗試在PHP中爲Windows創建類似inetd的服務,以便將來與我的其他應用程序一起使用。PHP Socket和proc_open

所以我所能想到的就是使用Steam服務器和proc_open將流直接傳送到進程(如inetd)。因爲在Windows上沒有pcntl_fork(),並且PHP不支持線程。

到目前爲止,這裏是我的代碼。該inetdtest程序是一個簡單的程序與單一printf(用C編寫)。但問題是,當我連接到我的服務器(通過netcat),我沒有得到任何迴應。

<?php 
define ('SERVICE_COMMAND', 'inetdtest'); 
define ('SERVICE_PORT', 35123); 

function main() { 
    echo "Simple inetd starting...\n"; 
    $socket = stream_socket_server('tcp://0.0.0.0:' . SERVICE_PORT, $errno, $errstr, STREAM_SERVER_BIND|STREAM_SERVER_LISTEN); 


    if ($socket === false) { 
     echo "Can't bind to service port.\n"; 
     echo "[$errno] $errstr"; 
     die(1); 
    } 
    $processes = array(); 
    while (true) { 
     $current = @stream_socket_accept($socket, 5, $host); 
     if ($current !== false) { 
      echo 'Incomming connection from client ' . $host . "\n"; 
      echo "Lunching child process... "; 

      $io = array(
       0 => $current, 
       1 => $current, 
       2 => array('file', 'stderr.log', 'a') 
      ); 

      $proc = proc_open(SERVICE_COMMAND, $io, $pipes, NULL, NULL, array('bypass_shell')); 
      $status = proc_get_status($proc); 
      echo " DONE! PID : {$status['pid']}\n"; 
      $processes[] = array($current, $proc); 
     } 
     foreach ($processes as $k=>$v) { 
      $status = proc_get_status($v[1]); 
      if (false === $status['running']) { 
       echo "Finalizing process {$status['pid']}... "; 
       fflush($v[0]); 
       fclose($v[0]); 
       proc_close($v[1]); 
       unset($processes[$k]); 
       echo "DONE!\n"; 
      } 
     } 
    } 
} 
main(); 

回答

1

代碼甫一的作品,因爲它站在這裏(用cat作爲程序和Linux上),所以問題在於事物的窗戶邊的地方。

一方面,要傳遞的選項,繞過外殼,應給出

array('bypass_shell'=>true) 

這可能已經解決的事情。這些棘手的部分是,你將一個套接字 fd傳遞給一個進程,這個進程可能會或可能不會被正確處理。我不知道這些事情是如何在Windows中完成的,但將cmd排除在等式之外只會有所幫助。

如果仍然無法工作,則應該創建一個等待數據(來自網絡或子進程)的循環,並將數據從網絡套接字發送到進程管道,反之亦然。