当前位置:首页 > PHP教程 > php高级应用 > 列表

php开启多进程的方法

发布:smiling 来源: PHP粉丝网  添加日期:2021-05-15 14:54:50 浏览: 评论:0 

这篇文章主要介绍了php开启多进程的方法,实例分析了php线程的使用技巧,需要的朋友可以参考下。

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

  1. <?php 
  2.  $IP='192.168.1.1';//Windows電腦的IP 
  3.  $Port='5900';        //VNC使用的Port 
  4.  $ServerPort='9999';//Linux Server對外使用的Port 
  5.  $RemoteSocket=false;//連線到VNC的Socket 
  6.  function SignalFunction($Signal){ 
  7.   //這是主Process的訊息處理函數 
  8.  global $PID;//Child Process的PID 
  9.  switch ($Signal
  10.  { 
  11.   case SIGTRAP: 
  12.   case SIGTERM: 
  13.    //收到結束程式的Signal 
  14.    if($PID
  15.    { 
  16.     //送一個SIGTERM的訊號給Child告訴他趕快結束掉嘍 
  17.     posix_kill($PID,SIGTERM); 
  18.     //等待Child Process結束,避免zombie 
  19.     pcntl_wait($Status); 
  20.    } 
  21.    //關閉主Process開啟的Socket 
  22.    DestroySocket(); 
  23.    exit(0); //結束主Process 
  24.    break
  25.   case SIGCHLD: 
  26.    /* 
  27. 當Child Process結束掉時,Child會送一個SIGCHLD訊號給Parrent 
  28. 當Parrent收到SIGCHLD,就知道Child Process已經結束嘍 ,該做一些 
  29. 結束的動作*/ 
  30.    unset($PID); //將$PID清空,表示Child Process已經結束 
  31.    pcntl_wait($Status); //避免Zombie 
  32.    break
  33.   default
  34.  } 
  35.  } 
  36.  function ChildSignalFunction($Signal){ 
  37. //這是Child Process的訊息處理函數 
  38.  switch ($Signal
  39.  { 
  40.   case SIGTRAP: 
  41.   case SIGTERM: 
  42. //Child Process收到結束的訊息 
  43.    DestroySocket(); //關閉Socket 
  44.    exit(0); //結束Child Process 
  45.   default
  46.  } 
  47.  } 
  48.  function ProcessSocket($ConnectedServerSocket){ 
  49.  //Child Process Socket處理函數 
  50.  //$ConnectedServerSocket -> 外部連進來的Socket 
  51.  global $ServerSocket,$RemoteSocket,$IP,$Port
  52.  $ServerSocket=$ConnectedServerSocket
  53.  declare(ticks = 1); //這一行一定要加,不然沒辦法設定訊息處理函數。 
  54. //設定訊息處理函數 
  55.  if(!pcntl_signal(SIGTERM, "ChildSignalFunction")) return
  56.  if(!pcntl_signal(SIGTRAP, "ChildSignalFunction")) return
  57. //建立一個連線到VNC的Socket 
  58.  $RemoteSocket=socket_create(AF_INET, SOCK_STREAM,SOL_TCP); 
  59. //連線到內部的VNC 
  60.  @$RemoteConnected=socket_connect($RemoteSocket,$IP,$Port); 
  61.  if(!$RemoteConnectedreturn//無法連線到VNC 結束 
  62. //將Socket的處理設為Nonblock,避免程式被Block住 
  63.  if(!socket_set_nonblock($RemoteSocket)) return
  64.  if(!socket_set_nonblock($ServerSocket)) return
  65.  while(true) 
  66.  { 
  67. //這邊我們採用pooling的方式去取得資料 
  68.   $NoRecvData=false;   //這個變數用來判別外部的連線是否有讀到資料 
  69.   $NoRemoteRecvData=false;//這個變數用來判別VNC連線是否有讀到資料 
  70.   @$RecvData=socket_read($ServerSocket,4096,PHP_BINARY_READ); 
  71. //從外部連線讀取4096 bytes的資料 
  72.   @$RemoteRecvData=socket_read($RemoteSocket,4096,PHP_BINARY_READ); 
  73. //從vnc連線連線讀取4096 bytes的資料 
  74.   if($RemoteRecvData===''
  75.   { 
  76. //VNC連線中斷,該結束嘍 
  77.    echo"Remote Connection Close\n"
  78.    return;   
  79.   } 
  80.   if($RemoteRecvData===false) 
  81.   { 
  82. /* 
  83. 由於我們是採用nonblobk模式 
  84. 這裡的情況就是vnc連線沒有可供讀取的資料 
  85. */ 
  86.    $NoRemoteRecvData=true; 
  87. //清除掉Last Errror 
  88.    socket_clear_error($RemoteSocket); 
  89.   } 
  90.   if($RecvData===''
  91.   { 
  92. //外部連線中斷,該結束嘍 
  93.    echo"Client Connection Close\n"
  94.    return
  95.   } 
  96.   if($RecvData===false) 
  97.   { 
  98. /* 
  99. 由於我們是採用nonblobk模式 
  100. 這裡的情況就是外部連線沒有可供讀取的資料 
  101. */ 
  102.    $NoRecvData=true; 
  103. //清除掉Last Errror 
  104.    socket_clear_error($ServerSocket); 
  105.   } 
  106.   if($NoRecvData&&$NoRemoteRecvData
  107.   { 
  108. //如果外部連線以及VNC連線都沒有資料可以讀取時, 
  109. //就讓程式睡個0.1秒,避免長期佔用CPU資源 
  110.    usleep(100000); 
  111. //睡醒後,繼續作pooling的動作讀取socket 
  112.    continue
  113.   } 
  114.   //Recv Data 
  115.   if(!$NoRecvData
  116.   { 
  117. //外部連線讀取到資料 
  118.    while(true) 
  119.    { 
  120. //把外部連線讀到的資料,轉送到VNC連線上 
  121.     @$WriteLen=socket_write($RemoteSocket,$RecvData); 
  122.     if($WriteLen===false) 
  123.     { 
  124. //由於網路傳輸的問題,目前暫時無法寫入資料 
  125. //先睡個0.1秒再繼續嘗試。 
  126.      usleep(100000); 
  127.      continue
  128.     } 
  129.     if($WriteLen===0) 
  130.     { 
  131. //遠端連線中斷,程式該結束了 
  132.      echo"Remote Write Connection Close\n"
  133.      return
  134.     } 
  135. //從外部連線讀取的資料,已經完全送給VNC連線時,中斷這個迴圈。 
  136.     if($WriteLen==strlen($RecvData)) break
  137. //如果資料一次送不完就得拆成好幾次傳送,直到所有的資料全部送出為止 
  138.     $RecvData=substr($RecvData,$WriteLen); 
  139.    } 
  140.   } 
  141.   if(!$NoRemoteRecvData
  142.   { 
  143. //這邊是從VNC連線讀取到的資料,再轉送回外部的連線 
  144. //原理跟上面差不多不再贅述 
  145.    while(true) 
  146.    { 
  147.     @$WriteLen=socket_write($ServerSocket,$RemoteRecvData); 
  148.     if($WriteLen===false) 
  149.     { 
  150.      usleep(100000); 
  151.      continue
  152.     } 
  153.     if($WriteLen===0) 
  154.     { 
  155.      echo"Remote Write Connection Close\n"
  156.      return
  157.     } 
  158.     if($WriteLen==strlen($RemoteRecvData)) break
  159.     $RemoteRecvData=substr($RemoteRecvData,$WriteLen); 
  160.    } 
  161.   } 
  162.  } 
  163.  } 
  164.  function DestroySocket(){ 
  165. //用來關閉已經開啟的Socket 
  166.  global$ServerSocket,$RemoteSocket
  167.  if($RemoteSocket
  168.  { 
  169. //如果已經開啟VNC連線 
  170. //在Close Socket前必須將Socket shutdown不然對方不知到你已經關閉連線了 
  171.   @socket_shutdown($RemoteSocket,2); 
  172.   socket_clear_error($RemoteSocket); 
  173. //關閉Socket 
  174.   socket_close($RemoteSocket);   
  175.  } 
  176. //關閉外部的連線 
  177.  @socket_shutdown($ServerSocket,2); 
  178.  socket_clear_error($ServerSocket); 
  179.  socket_close($ServerSocket); 
  180.  } 
  181. //這裡是整個程式的開頭,程式從這邊開始執行 
  182. //這裡首先執行一次fork 
  183.  $PID=pcntl_fork(); 
  184.  if($PID==-1) die("could not fork"); 
  185. //如果$PID不為0表示這是Parrent Process 
  186. //$PID就是Child Process 
  187. //這是Parrent Process 自己結束掉,讓Child成為一個Daemon。 
  188.  if($PIDdie("Daemon PID:$PID\n"); 
  189. //從這邊開始,就是Daemon模式在執行了 
  190. //將目前的Process跟終端機脫離成為daemon模式 
  191.  if(!posix_setsid()) die("could not detach from terminal\n"); 
  192. //設定daemon 的訊息處理函數 
  193.  declare(ticks = 1); 
  194.  if(!pcntl_signal(SIGTERM, "SignalFunction")) die("Error!!!\n"); 
  195.  if(!pcntl_signal(SIGTRAP, "SignalFunction")) die("Error!!!\n"); 
  196.  if(!pcntl_signal(SIGCHLD, "SignalFunction")) die("Error!!!\n"); 
  197. //建立外部連線的Socket 
  198.  $ServerSocket=socket_create(AF_INET, SOCK_STREAM,SOL_TCP); 
  199. //設定外部連線監聽的IP以及Port,IP欄位設0,表示經聽所有介面的IP 
  200.  if(!socket_bind($ServerSocket,0,$ServerPort)) die("Cannot Bind Socket!\n"); 
  201. //開始監聽Port 
  202.  if(!socket_listen($ServerSocket)) die("Cannot Listen!\n"); 
  203. //將Socket設為nonblock模式 
  204.  if(!socket_set_nonblock($ServerSocket)) die("Cannot Set Server Socket to Block!\n"); 
  205. //清空$PID變數,表示目前沒有任何的Child Process 
  206.  unset($PID); 
  207.  while(true) 
  208.  { 
  209. //進入pooling模式,每隔1秒鐘就去檢查有沒有連線進來。 
  210.   sleep(1); 
  211. //檢查有沒有連線進來 
  212.   @$ConnectedServerSocket=socket_accept($ServerSocket); 
  213.   if($ConnectedServerSocket!==false) 
  214.   { 
  215. //有人連進來嘍 
  216. //起始一個Child Process用來處理連線 
  217.    $PID=pcntl_fork(); 
  218.    if($PID==-1) die("could not fork"); 
  219.    if($PIDcontinue;//這是daemon process,繼續回去監聽。 
  220.    //這裡是Child Process開始 
  221.    //執行Socket裡函數 
  222.    ProcessSocket($ConnectedServerSocket); 
  223.   //處理完Socket後,結束掉Socket 
  224.    DestroySocket(); 
  225.   //結束Child Process 
  226.    exit(0); 
  227.   } 
  228.  }

Tags: php开启多进程

分享到: