2010-07-31 66 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排除在等式之外只会有所帮助。

如果仍然无法工作,则应该创建一个等待数据(来自网络或子进程)的循环,并将数据从网络套接字发送到进程管道,反之亦然。