Net_Server
[ class tree: Net_Server ] [ index: Net_Server ] [ all elements ]

Source for file Multiprocess.php

Documentation is available at Multiprocess.php

  1. <?php
  2. /**
  3.  * Originally coded by the author Stephan Schmidt
  4.  * and committed to PEAR repository.
  5.  *
  6.  * Deep modifications was been made since that day...
  7.  * Into PEAR you can actually found the base class (Server.php)
  8.  * the handler base class (Handler.php) and the sequential driver (Sequential.php)
  9.  *
  10.  * I developed both multiprocess driver and Multi Processing Modules (actually only preforking)
  11.  * specifically for phplet project.
  12.  * Hope this stuff can be committed to PEAR one day!
  13.  *
  14.  * @author Stephan Schmidt <schst@php.net>
  15.  */
  16. require_once 'PEAR.php';
  17. require_once 'PHP/Fork.php';
  18. require_once 'Net/Server/Driver.php';
  19. require_once 'Net/Server/Driver/Multiprocess/remoteConsole.php';
  20. require_once 'Net/Server/Driver/Multiprocess/Processor.php';
  21.  
  22.     var $_numThreads;
  23.     var $_startPool;
  24.     var $_maxIdleTime;
  25.     var $_threadPool;
  26.     var $_mpm;
  27.     var $_console;
  28.  
  29.     var $_mpmObj;
  30.     var $_consoleObj;
  31.  
  32.     /**
  33.      * set maximum amount of simultaneous connections
  34.      * that's to say the maximum number of listener processes
  35.      * that this server can handle
  36.      *
  37.      * @access public
  38.      * @param int $maxClients 
  39.      */
  40.     function setMaxClients($maxClients)
  41.     {
  42.         $this->_numThreads $maxClients;
  43.     }
  44.  
  45.     /**
  46.      * set the initial number of listener processes
  47.      *
  48.      * @access public
  49.      * @param int $dim 
  50.      */
  51.     function setStartPool($dim)
  52.     {
  53.         $this->_startPool $dim;
  54.     }
  55.  
  56.     /**
  57.      * set the maximun time a process can be sleeping
  58.      * (without serving any request) before MPM kill it
  59.      * NOT USED AT THIS MOMENT
  60.      *
  61.      * @access public
  62.      * @param int $secs 
  63.      */
  64.     function setMaxIdle($secs)
  65.     {
  66.         $this->_maxIdleTime $secs;
  67.     }
  68.  
  69.     /**
  70.      * set the MPM layout for this server
  71.      * (only preforkg avaible for now)
  72.      *
  73.      * @access public
  74.      * @param string $mpm 
  75.      */
  76.     function setMPM($mpm)
  77.     {
  78.         $this->_mpm $mpm;
  79.     }
  80.  
  81.     /**
  82.      * set the console class for this server
  83.      *
  84.      * @access public
  85.      * @param string $classname 
  86.      */
  87.     function setConsole($classname)
  88.     {
  89.         $this->_console $classname;
  90.     }
  91.  
  92.     /**
  93.      * start the server
  94.      *
  95.      * @access public
  96.      */
  97.     function start()
  98.     {
  99.         if (!function_exists('pcntl_fork')) {
  100.             die ('Needs pcntl extension to fork processes.');
  101.         }
  102.  
  103.         $this->initFD @socket_create($this->protocolSOCK_STREAM0);
  104.         if (!$this->initFD{
  105.             die ("Could not create socket.");
  106.         }
  107.         // adress may be reused
  108.         socket_setopt($this->initFDSOL_SOCKETSO_REUSEADDR1);
  109.         // bind the socket
  110.         if (!@socket_bind($this->initFD$this->domain$this->port)) {
  111.             $error $this->getLastSocketError($this->initFd);
  112.             @socket_close($this->initFD);
  113.             die ("Could not bind socket to " $this->domain " on port " $this->port " (" $error ").");
  114.         }
  115.         // listen on selected port
  116.         if (!@socket_listen($this->initFD$this->maxQueue)) {
  117.             $error $this->getLastSocketError($this->initFd);
  118.             @socket_close($this->initFD);
  119.             die ("Could not listen (" $error ").");
  120.         }
  121.  
  122.         $this->_sendDebugMessage("Listening on port " $this->port ". Server started at " date("H:i:s"time()));
  123.  
  124.         if (method_exists($this->callbackObj"onStart")) {
  125.             $this->callbackObj->onStart();
  126.         }
  127.  
  128.         $this->_setDefaultOptions();
  129.  
  130.         $mpmDriverFile 'Net/Server/Driver/Multiprocess/MPM-' $this->_mpm '.php';
  131.  
  132.         if (!@include_once $mpmDriverFile{
  133.             die ('Unknown MPM ' $mpmDriverFile);
  134.         }
  135.         // starting pool of processors...
  136.         for ($i = 0; $i $this->_startPool$i++{
  137.             $this->_threadPool[$inew Net_Server_Thread_Processor($i$this);
  138.             $this->_threadPool[$i]->start();
  139.  
  140.             print("Started Processor " $i " with PID " $this->_threadPool[$i]->getPid("\n");
  141.         }
  142.         // Multi Process Manager
  143.         $this->_mpmObj new MPM($this->_threadPool$this);
  144.         $this->_mpmObj->start();
  145.         print("Started MPM with PID " $this->_mpmObj->getPid("\n");
  146.         // destroy the listening primar socket, it's unuseful at this point
  147.         @socket_close($this->initFD);
  148.         // remote console thread
  149.         $consoleClassName $this->_console;
  150.         if (!@include_once ('Net/Server/Driver/Multiprocess/'.$consoleClassName.'.php')) {
  151.             die ('Unknown console ' $consoleClassName);
  152.         }
  153.         $this->_consoleObj new $consoleClassName($this);
  154.         $this->_consoleObj->start();
  155.         print("Started remote console with PID " $this->_consoleObj->getPid("\n");
  156.     }
  157.  
  158.     /**
  159.      * check, whether a client is still connected
  160.      *
  161.      * @access public
  162.      * @param integer $id client id
  163.      * @return boolean $connected  true if client is connected, false otherwise
  164.      */
  165.     function isConnected($i)
  166.     {
  167.         if (is_resource($this->clientFD[$i])) {
  168.             return true;
  169.         }
  170.     }
  171.  
  172.     /**
  173.      * get current amount of clients
  174.      *
  175.      * @access public
  176.      * @return int $clients    amount of clients
  177.      */
  178.     function getClients()
  179.     {
  180.         $overview $this->_mpmObj->getProcOverview();
  181.         return $overview['working'];
  182.     }
  183.  
  184.     /**
  185.      * send data to a client
  186.      *
  187.      * @access public
  188.      * @param int $clientId ID of the client
  189.      * @param string $data data to send
  190.      * @param boolean $debugData flag to indicate whether data that is written to socket should also be sent as debug message
  191.      */
  192.     function sendData($clientId$data$debugData = true)
  193.     {
  194.     //print_r ($this);
  195.         if (!isset($this->clientFD[$clientId]|| $this->clientFD[$clientId== null{
  196.             
  197.             return $this->raiseError("Client $clientId does not exist. (193)");
  198.         }
  199.  
  200.         if ($debugData{
  201.             $this->_sendDebugMessage("sending: \"" $data . "\" to: $clientId");
  202.         }
  203.         if (!@socket_write($this->clientFD[$clientId]$data)) {
  204.             $this->_sendDebugMessage("Could not write '" $data "' client " $clientId " (" $this->getLastSocketError($this->clientFD[$clientId]").");
  205.         }
  206.     }
  207.  
  208.     /**
  209.      * send data to all clients
  210.      *
  211.      * @access public
  212.      * @param string $data data to send
  213.      * @param array $exclude client ids to exclude
  214.      */
  215.     function broadcastData($data$exclude = array())
  216.     {
  217.         $this->sendData($data);
  218.     }
  219.  
  220.     /**
  221.      * get current information about a client
  222.      *
  223.      * @access public
  224.      * @param int $i ID of the client
  225.      * @return array $info        information about the client
  226.      */
  227.     function getClientInfo($i)
  228.     {
  229.         if (!isset($this->clientFD[$i]|| $this->clientFD[$i== null{
  230.             return $this->raiseError("Client does not exist.(226)");
  231.         }
  232.         return $this->clientInfo[$i];
  233.     }
  234.  
  235.     /**
  236.      * close connection to a client
  237.      *
  238.      * @access public
  239.      * @param int $i internal ID of the client
  240.      */
  241.     function closeConnection($i = 0)
  242.     {
  243.         if (!isset($this->clientFD[$i])) {
  244.             return $this->raiseError("Connection already has been closed.");
  245.         }
  246.  
  247.         if (method_exists($this->callbackObj"onClose")) {
  248.             $this->callbackObj->onClose($i);
  249.         }
  250.  
  251.         $this->_sendDebugMessage(
  252.             "Closed connection from " $this->clientInfo[$i]["host"
  253.             . " on port " $this->clientInfo[$i]["port"]
  254.         );
  255.  
  256.         @socket_close($this->clientFD[$i]);
  257.         $this->clientFD[$i= null;
  258.         unset($this->clientInfo[$i]);
  259.     }
  260.  
  261.     /**
  262.      * Shutdown server
  263.      * ---------------------------- ATTENTION -------------------------------------
  264.      * On multiprocess layouts stopping the server ==> stopping all processes
  265.      * that are listening on server port; we generally can't do this operation
  266.      * from the same server instance, because it only knows of the existence of processes
  267.      * that it forked at start(). This start pool is equivalent to running pool in every
  268.      * moment only if we're running the MPM-static.
  269.      * With more complex MPM like the pre-forking one the process responsible for forking
  270.      * new listeners at run-time  is MPM, so we must make a call to it in order
  271.      * to stop all forked processes.
  272.      * Of course if we have a running MPM and a running console, stopping the server
  273.      * requires stopping them too.
  274.      *
  275.      * @access public
  276.      */
  277.     function shutDown()
  278.     {
  279.         if (method_exists($this->callbackObj"onShutdown")) {
  280.             $this->callbackObj->onShutdown();
  281.         }
  282.  
  283.         // this always should return true, we use PHP_FORK_RETURN_METHOD because
  284.         // we want to wait until all processes are really stopped...
  285.         if ($this->_mpmObj->stopAllProcesses(array('')PHP_FORK_RETURN_METHOD)) {
  286.             print "Stopping " $this->_mpmObj->getName("\n";
  287.             $this->_mpmObj->stop();
  288.  
  289.             print "Exiting from console...\n";
  290.         else {
  291.             print "Error stopping mpm\n";
  292.         }
  293.  
  294.         $this->closeConnection();
  295.         $this->_consoleObj->stop();
  296.     }
  297.  
  298.     function raiseError($msg)
  299.     {
  300.         $this->_sendDebugMessage("ERROR: " $msg);
  301.     }
  302.  
  303.     /**
  304.      * set some default options that are needed to run
  305.      * a multiprocess server; usually we override this
  306.      * with custom values.
  307.      *
  308.      * @access private
  309.      */
  310.     function _setDefaultOptions()
  311.     {
  312.         if (!isset($this->_numThreads)) {
  313.             $this->_numThreads = 10;
  314.         }
  315.  
  316.         if (!isset($this->_startPool)) {
  317.             $this->_startPool = 2;
  318.         }
  319.  
  320.         if (!isset($this->_maxIdleTime)) {
  321.             $this->_maxIdleTime = 60;
  322.         }
  323.  
  324.         if (!isset($this->_mpm)) {
  325.             $this->_mpm "prefork";
  326.         }
  327.  
  328.         if (!isset($this->_console)) {
  329.             $this->_console "remoteConsole";
  330.         }
  331.  
  332.     }
  333.  
  334. }
  335.  
  336. ?>

Documentation generated on Mon, 11 Mar 2019 15:47:10 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.