首页 > 编程 > PHP > 正文

php开启多进程的方法

2019-11-21 23:15:03
字体:
来源:转载
供稿:网友

本文实例讲述了php开启多进程的方法。分享给大家供大家参考。具体实现方法如下:

复制代码 代码如下:

<?php
 $IP='192.168.1.1';//Windows的IP
 $Port='5900';        //VNC使用的Port
 $ServerPort='9999';//Linux Server外使用的Port
 $RemoteSocket=false;//到VNC的Socket
 function SignalFunction($Signal){
  //是主Process的息理函
 global $PID;//Child Process的PID
 switch ($Signal)
 {
  case SIGTRAP:
  case SIGTERM:
   //收到束程式的Signal
   if($PID)
   {
    //送一SIGTERM的Child告他快束掉
    posix_kill($PID,SIGTERM);
    //等待Child Process束,避免zombie
    pcntl_wait($Status);
   }
   //主Process的Socket
   DestroySocket();
   exit(0); //束主Process
   break;
  case SIGCHLD:
   /*
Child Process束掉,Child送一SIGCHLDParrent
Parrent收到SIGCHLD,就知道Child Process已束 ,做一些
束的作*/
   unset($PID); //$PID清空,表示Child Process已束
   pcntl_wait($Status); //避免Zombie
   break;
  default:
 }
 }
 function ChildSignalFunction($Signal){
//是Child Process的息理函
 switch ($Signal)
 {
  case SIGTRAP:
  case SIGTERM:
//Child Process收到束的息
   DestroySocket(); //Socket
   exit(0); //束Child Process
  default:
 }
 }
 function ProcessSocket($ConnectedServerSocket){
 //Child Process Socket理函
 //$ConnectedServerSocket -> 外部的Socket
 global $ServerSocket,$RemoteSocket,$IP,$Port;
 $ServerSocket=$ConnectedServerSocket;
 declare(ticks = 1); //一行一定要加,不然法定息理函。
//定息理函
 if(!pcntl_signal(SIGTERM, "ChildSignalFunction")) return;
 if(!pcntl_signal(SIGTRAP, "ChildSignalFunction")) return;
//建立一到VNC的Socket
 $RemoteSocket=socket_create(AF_INET, SOCK_STREAM,SOL_TCP);
//到部的VNC
 @$RemoteConnected=socket_connect($RemoteSocket,$IP,$Port);
 if(!$RemoteConnected) return; //法到VNC 束
//Socket的理Nonblock,避免程式被Block住
 if(!socket_set_nonblock($RemoteSocket)) return;
 if(!socket_set_nonblock($ServerSocket)) return;
 while(true)
 {
//我用pooling的方式去取得料
  $NoRecvData=false;   //用判外部的是否有到料
  $NoRemoteRecvData=false;//用判VNC是否有到料
  @$RecvData=socket_read($ServerSocket,4096,PHP_BINARY_READ);
//外部取4096 bytes的料
  @$RemoteRecvData=socket_read($RemoteSocket,4096,PHP_BINARY_READ);
//vnc取4096 bytes的料
  if($RemoteRecvData==='')
  {
//VNC中,束
   echo"Remote Connection Close/n";
   return;  
  }
  if($RemoteRecvData===false)
  {
/*
由於我是用nonblobk模式
的情就是vnc有可供取的料
*/
   $NoRemoteRecvData=true;
//清除掉Last Errror
   socket_clear_error($RemoteSocket);
  }
  if($RecvData==='')
  {
//外部中,束
   echo"Client Connection Close/n";
   return;
  }
  if($RecvData===false)
  {
/*
由於我是用nonblobk模式
的情就是外部有可供取的料
*/
   $NoRecvData=true;
//清除掉Last Errror
   socket_clear_error($ServerSocket);
  }
  if($NoRecvData&&$NoRemoteRecvData)
  {
//如果外部以及VNC都有料可以取,
//就程式睡0.1秒,避免期用CPU源
   usleep(100000);
//睡醒後,作pooling的作取socket
   continue;
  }
  //Recv Data
  if(!$NoRecvData)
  {
//外部取到料
   while(true)
   {
//把外部到的料,送到VNC上
    @$WriteLen=socket_write($RemoteSocket,$RecvData);
    if($WriteLen===false)
    {
//由於路的,目前法入料
//先睡0.1秒再。
     usleep(100000);
     continue;
    }
    if($WriteLen===0)
    {
//端中,程式束了
     echo"Remote Write Connection Close/n";
     return;
    }
//外部取的料,已完全送VNC,中圈。
    if($WriteLen==strlen($RecvData)) break;
//如果料一次送不完就得拆成好次送,直到所有的料全部送出止
    $RecvData=substr($RecvData,$WriteLen);
   }
  }
  if(!$NoRemoteRecvData)
  {
//是VNC取到的料,再送回外部的
//原理跟上面差不多不再述
   while(true)
   {
    @$WriteLen=socket_write($ServerSocket,$RemoteRecvData);
    if($WriteLen===false)
    {
     usleep(100000);
     continue;
    }
    if($WriteLen===0)
    {
     echo"Remote Write Connection Close/n";
     return;
    }
    if($WriteLen==strlen($RemoteRecvData)) break;
    $RemoteRecvData=substr($RemoteRecvData,$WriteLen);
   }
  }
 }
 }
 function DestroySocket(){
//用已的Socket
 global$ServerSocket,$RemoteSocket;
 if($RemoteSocket)
 {
//如果已VNC
//在Close Socket前必Socket shutdown不然方不知到你已了
  @socket_shutdown($RemoteSocket,2);
  socket_clear_error($RemoteSocket);
//Socket
  socket_close($RemoteSocket);  
 }
//外部的
 @socket_shutdown($ServerSocket,2);
 socket_clear_error($ServerSocket);
 socket_close($ServerSocket);
 }
//是整程式的,程式始行
//首先行一次fork
 $PID=pcntl_fork();
 if($PID==-1) die("could not fork");
//如果$PID不0表示是Parrent Process
//$PID就是Child Process
//是Parrent Process 自己束掉,Child成一Daemon。
 if($PID) die("Daemon PID:$PID/n");
//始,就是Daemon模式在行了
//目前的Process跟端成daemon模式
 if(!posix_setsid()) die("could not detach from terminal/n");
//定daemon 的息理函
 declare(ticks = 1);
 if(!pcntl_signal(SIGTERM, "SignalFunction")) die("Error!!!/n");
 if(!pcntl_signal(SIGTRAP, "SignalFunction")) die("Error!!!/n");
 if(!pcntl_signal(SIGCHLD, "SignalFunction")) die("Error!!!/n");
//建立外部的Socket
 $ServerSocket=socket_create(AF_INET, SOCK_STREAM,SOL_TCP);
//定外部的IP以及Port,IP位0,表示所有介面的IP
 if(!socket_bind($ServerSocket,0,$ServerPort)) die("Cannot Bind Socket!/n");
//始Port
 if(!socket_listen($ServerSocket)) die("Cannot Listen!/n");
//Socketnonblock模式
 if(!socket_set_nonblock($ServerSocket)) die("Cannot Set Server Socket to Block!/n");
//清空$PID,表示目前有任何的Child Process
 unset($PID);
 while(true)
 {
//入pooling模式,每隔1秒就去查有有。
  sleep(1);
//查有有
  @$ConnectedServerSocket=socket_accept($ServerSocket);
  if($ConnectedServerSocket!==false)
  {
//有人
//起始一Child Process用理
   $PID=pcntl_fork();
   if($PID==-1) die("could not fork");
   if($PID) continue;//是daemon process,回去。
   //是Child Process始
   //行Socket函
   ProcessSocket($ConnectedServerSocket);
  //理完Socket後,束掉Socket
   DestroySocket();
  //束Child Process
   exit(0);
  }
 }

希望本文所述对大家的php程序设计有所帮助。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表