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

Source for file Socket.php

Documentation is available at Socket.php

  1. <?php
  2. /**
  3.  * Net_Socket
  4.  *
  5.  * PHP Version 4
  6.  *
  7.  * Copyright (c) 1997-2013 The PHP Group
  8.  *
  9.  * This source file is subject to version 2.0 of the PHP license,
  10.  * that is bundled with this package in the file LICENSE, and is
  11.  * available at through the world-wide-web at
  12.  * http://www.php.net/license/2_02.txt.
  13.  * If you did not receive a copy of the PHP license and are unable to
  14.  * obtain it through the world-wide-web, please send a note to
  15.  * license@php.net so we can mail you a copy immediately.
  16.  *
  17.  * Authors: Stig Bakken <ssb@php.net>
  18.  *          Chuck Hagenbuch <chuck@horde.org>
  19.  *
  20.  * @category  Net
  21.  * @package   Net_Socket
  22.  * @author    Stig Bakken <ssb@php.net>
  23.  * @author    Chuck Hagenbuch <chuck@horde.org>
  24.  * @copyright 1997-2003 The PHP Group
  25.  * @license   http://www.php.net/license/2_02.txt PHP 2.02
  26.  * @link      http://pear.php.net/packages/Net_Socket
  27.  */
  28.  
  29. require_once 'PEAR.php';
  30.  
  31. define('NET_SOCKET_READ'1);
  32. define('NET_SOCKET_WRITE'2);
  33. define('NET_SOCKET_ERROR'4);
  34.  
  35. /**
  36.  * Generalized Socket class.
  37.  *
  38.  * @category  Net
  39.  * @package   Net_Socket
  40.  * @author    Stig Bakken <ssb@php.net>
  41.  * @author    Chuck Hagenbuch <chuck@horde.org>
  42.  * @copyright 1997-2003 The PHP Group
  43.  * @license   http://www.php.net/license/2_02.txt PHP 2.02
  44.  * @link      http://pear.php.net/packages/Net_Socket
  45.  */
  46. class Net_Socket extends PEAR
  47. {
  48.     /**
  49.      * Socket file pointer.
  50.      * @var resource $fp 
  51.      */
  52.     var $fp = null;
  53.  
  54.     /**
  55.      * Whether the socket is blocking. Defaults to true.
  56.      * @var boolean $blocking 
  57.      */
  58.     var $blocking = true;
  59.  
  60.     /**
  61.      * Whether the socket is persistent. Defaults to false.
  62.      * @var boolean $persistent 
  63.      */
  64.     var $persistent = false;
  65.  
  66.     /**
  67.      * The IP address to connect to.
  68.      * @var string $addr 
  69.      */
  70.     var $addr = '';
  71.  
  72.     /**
  73.      * The port number to connect to.
  74.      * @var integer $port 
  75.      */
  76.     var $port = 0;
  77.  
  78.     /**
  79.      * Number of seconds to wait on socket operations before assuming
  80.      * there's no more data. Defaults to no timeout.
  81.      * @var integer|float$timeout 
  82.      */
  83.     var $timeout = null;
  84.  
  85.     /**
  86.      * Number of bytes to read at a time in readLine() and
  87.      * readAll(). Defaults to 2048.
  88.      * @var integer $lineLength 
  89.      */
  90.     var $lineLength = 2048;
  91.  
  92.     /**
  93.      * The string to use as a newline terminator. Usually "\r\n" or "\n".
  94.      * @var string $newline 
  95.      */
  96.     var $newline = "\r\n";
  97.  
  98.     /**
  99.      * Connect to the specified port. If called when the socket is
  100.      * already connected, it disconnects and connects again.
  101.      *
  102.      * @param string  $addr       IP address or host name (may be with protocol prefix).
  103.      * @param integer $port       TCP port number.
  104.      * @param boolean $persistent (optional) Whether the connection is
  105.      *                             persistent (kept open between requests
  106.      *                             by the web server).
  107.      * @param integer $timeout    (optional) Connection socket timeout.
  108.      * @param array   $options    See options for stream_context_create.
  109.      *
  110.      * @access public
  111.      *
  112.      * @return boolean|PEAR_Error True on success or a PEAR_Error on failure.
  113.      */
  114.     function connect($addr$port = 0$persistent = null,
  115.                      $timeout = null$options = null)
  116.     {
  117.         if (is_resource($this->fp)) {
  118.             @fclose($this->fp);
  119.             $this->fp = null;
  120.         }
  121.  
  122.         if (!$addr{
  123.             return $this->raiseError('$addr cannot be empty');
  124.         else if (strspn($addr':.0123456789'== strlen($addr)) {
  125.             $this->addr = strpos($addr':'!== false ? '['.$addr.']' $addr;
  126.         else {
  127.             $this->addr = $addr;
  128.         }
  129.  
  130.         $this->port = $port % 65536;
  131.  
  132.         if ($persistent !== null{
  133.             $this->persistent = $persistent;
  134.         }
  135.  
  136.         $openfunc $this->persistent ? 'pfsockopen' 'fsockopen';
  137.         $errno    = 0;
  138.         $errstr   '';
  139.  
  140.         $old_track_errors @ini_set('track_errors'1);
  141.  
  142.         if ($timeout <= 0{
  143.             $timeout @ini_get('default_socket_timeout');
  144.         }
  145.  
  146.         if ($options && function_exists('stream_context_create')) {
  147.             $context stream_context_create($options);
  148.  
  149.             // Since PHP 5 fsockopen doesn't allow context specification
  150.             if (function_exists('stream_socket_client')) {
  151.                 $flags = STREAM_CLIENT_CONNECT;
  152.  
  153.                 if ($this->persistent{
  154.                     $flags = STREAM_CLIENT_PERSISTENT;
  155.                 }
  156.  
  157.                 $addr $this->addr . ':' $this->port;
  158.                 $fp   stream_socket_client($addr$errno$errstr,
  159.                                              $timeout$flags$context);
  160.             else {
  161.                 $fp @$openfunc($this->addr$this->port$errno,
  162.                                  $errstr$timeout$context);
  163.             }
  164.         else {
  165.             $fp @$openfunc($this->addr$this->port$errno$errstr$timeout);
  166.         }
  167.  
  168.         if (!$fp{
  169.             if ($errno == 0 && !strlen($errstr&& isset($php_errormsg)) {
  170.                 $errstr $php_errormsg;
  171.             }
  172.             @ini_set('track_errors'$old_track_errors);
  173.             return $this->raiseError($errstr$errno);
  174.         }
  175.  
  176.         @ini_set('track_errors'$old_track_errors);
  177.         $this->fp = $fp;
  178.         $this->setTimeout();
  179.         return $this->setBlocking($this->blocking);
  180.     }
  181.  
  182.     /**
  183.      * Disconnects from the peer, closes the socket.
  184.      *
  185.      * @access public
  186.      * @return mixed true on success or a PEAR_Error instance otherwise
  187.      */
  188.     function disconnect()
  189.     {
  190.         if (!is_resource($this->fp)) {
  191.             return $this->raiseError('not connected');
  192.         }
  193.  
  194.         @fclose($this->fp);
  195.         $this->fp = null;
  196.         return true;
  197.     }
  198.  
  199.     /**
  200.      * Set the newline character/sequence to use.
  201.      *
  202.      * @param string $newline  Newline character(s)
  203.      * @return boolean True
  204.      */
  205.     function setNewline($newline)
  206.     {
  207.         $this->newline = $newline;
  208.         return true;
  209.     }
  210.  
  211.     /**
  212.      * Find out if the socket is in blocking mode.
  213.      *
  214.      * @access public
  215.      * @return boolean  The current blocking mode.
  216.      */
  217.     function isBlocking()
  218.     {
  219.         return $this->blocking;
  220.     }
  221.  
  222.     /**
  223.      * Sets whether the socket connection should be blocking or
  224.      * not. A read call to a non-blocking socket will return immediately
  225.      * if there is no data available, whereas it will block until there
  226.      * is data for blocking sockets.
  227.      *
  228.      * @param boolean $mode True for blocking sockets, false for nonblocking.
  229.      *
  230.      * @access public
  231.      * @return mixed true on success or a PEAR_Error instance otherwise
  232.      */
  233.     function setBlocking($mode)
  234.     {
  235.         if (!is_resource($this->fp)) {
  236.             return $this->raiseError('not connected');
  237.         }
  238.  
  239.         $this->blocking = $mode;
  240.         stream_set_blocking($this->fp(int)$this->blocking);
  241.         return true;
  242.     }
  243.  
  244.     /**
  245.      * Sets the timeout value on socket descriptor,
  246.      * expressed in the sum of seconds and microseconds
  247.      *
  248.      * @param integer $seconds      Seconds.
  249.      * @param integer $microseconds Microseconds, optional.
  250.      *
  251.      * @access public
  252.      * @return mixed True on success or false on failure or
  253.      *                a PEAR_Error instance when not connected
  254.      */
  255.     function setTimeout($seconds = null$microseconds = null)
  256.     {
  257.         if (!is_resource($this->fp)) {
  258.             return $this->raiseError('not connected');
  259.         }
  260.  
  261.         if ($seconds === null && $microseconds === null{
  262.             $seconds      = (int) $this->timeout;
  263.             $microseconds = (int) (($this->timeout - $seconds* 1000000);
  264.         else {
  265.             $this->timeout = $seconds $microseconds/1000000;
  266.         }
  267.  
  268.         if ($this->timeout > 0{
  269.             return stream_set_timeout($this->fp(int) $seconds(int) $microseconds);
  270.         }
  271.         else {
  272.             return false;
  273.         }
  274.     }
  275.  
  276.     /**
  277.      * Sets the file buffering size on the stream.
  278.      * See php's stream_set_write_buffer for more information.
  279.      *
  280.      * @param integer $size Write buffer size.
  281.      *
  282.      * @access public
  283.      * @return mixed on success or an PEAR_Error object otherwise
  284.      */
  285.     function setWriteBuffer($size)
  286.     {
  287.         if (!is_resource($this->fp)) {
  288.             return $this->raiseError('not connected');
  289.         }
  290.  
  291.         $returned stream_set_write_buffer($this->fp$size);
  292.         if ($returned == 0{
  293.             return true;
  294.         }
  295.         return $this->raiseError('Cannot set write buffer.');
  296.     }
  297.  
  298.     /**
  299.      * Returns information about an existing socket resource.
  300.      * Currently returns four entries in the result array:
  301.      *
  302.      * <p>
  303.      * timed_out (bool) - The socket timed out waiting for data<br>
  304.      * blocked (bool) - The socket was blocked<br>
  305.      * eof (bool) - Indicates EOF event<br>
  306.      * unread_bytes (int) - Number of bytes left in the socket buffer<br>
  307.      * </p>
  308.      *
  309.      * @access public
  310.      * @return mixed Array containing information about existing socket
  311.      *                resource or a PEAR_Error instance otherwise
  312.      */
  313.     function getStatus()
  314.     {
  315.         if (!is_resource($this->fp)) {
  316.             return $this->raiseError('not connected');
  317.         }
  318.  
  319.         return stream_get_meta_data($this->fp);
  320.     }
  321.  
  322.     /**
  323.      * Get a specified line of data
  324.      *
  325.      * @param int $size Reading ends when size - 1 bytes have been read,
  326.      *                   or a newline or an EOF (whichever comes first).
  327.      *                   If no size is specified, it will keep reading from
  328.      *                   the stream until it reaches the end of the line.
  329.      *
  330.      * @access public
  331.      * @return mixed $size bytes of data from the socket, or a PEAR_Error if
  332.      *          not connected. If an error occurs, FALSE is returned.
  333.      */
  334.     function gets($size = null)
  335.     {
  336.         if (!is_resource($this->fp)) {
  337.             return $this->raiseError('not connected');
  338.         }
  339.  
  340.         if (is_null($size)) {
  341.             return @fgets($this->fp);
  342.         else {
  343.             return @fgets($this->fp$size);
  344.         }
  345.     }
  346.  
  347.     /**
  348.      * Read a specified amount of data. This is guaranteed to return,
  349.      * and has the added benefit of getting everything in one fread()
  350.      * chunk; if you know the size of the data you're getting
  351.      * beforehand, this is definitely the way to go.
  352.      *
  353.      * @param integer $size The number of bytes to read from the socket.
  354.      *
  355.      * @access public
  356.      * @return $size bytes of data from the socket, or a PEAR_Error if
  357.      *          not connected.
  358.      */
  359.     function read($size)
  360.     {
  361.         if (!is_resource($this->fp)) {
  362.             return $this->raiseError('not connected');
  363.         }
  364.  
  365.         return @fread($this->fp$size);
  366.     }
  367.  
  368.     /**
  369.      * Write a specified amount of data.
  370.      *
  371.      * @param string  $data      Data to write.
  372.      * @param integer $blocksize Amount of data to write at once.
  373.      *                            NULL means all at once.
  374.      *
  375.      * @access public
  376.      * @return mixed If the socket is not connected, returns an instance of
  377.      *                PEAR_Error.
  378.      *                If the write succeeds, returns the number of bytes written.
  379.      *                If the write fails, returns false.
  380.      *                If the socket times out, returns an instance of PEAR_Error.
  381.      */
  382.     function write($data$blocksize = null)
  383.     {
  384.         if (!is_resource($this->fp)) {
  385.             return $this->raiseError('not connected');
  386.         }
  387.  
  388.         if (is_null($blocksize&& !OS_WINDOWS{
  389.             $written @fwrite($this->fp$data);
  390.  
  391.             // Check for timeout or lost connection
  392.             if (!$written{
  393.                 $meta_data $this->getStatus();
  394.  
  395.                 if (!is_array($meta_data)) {
  396.                     return $meta_data// PEAR_Error
  397.                 }
  398.  
  399.                 if (!empty($meta_data['timed_out'])) {
  400.                     return $this->raiseError('timed out');
  401.                 }
  402.             }
  403.  
  404.             return $written;
  405.         else {
  406.             if (is_null($blocksize)) {
  407.                 $blocksize = 1024;
  408.             }
  409.  
  410.             $pos  = 0;
  411.             $size strlen($data);
  412.             while ($pos $size{
  413.                 $written @fwrite($this->fpsubstr($data$pos$blocksize));
  414.  
  415.                 // Check for timeout or lost connection
  416.                 if (!$written{
  417.                     $meta_data $this->getStatus();
  418.  
  419.                     if (!is_array($meta_data)) {
  420.                         return $meta_data// PEAR_Error
  421.                     }
  422.  
  423.                     if (!empty($meta_data['timed_out'])) {
  424.                         return $this->raiseError('timed out');
  425.                     }
  426.  
  427.                     return $written;
  428.                 }
  429.  
  430.                 $pos += $written;
  431.             }
  432.  
  433.             return $pos;
  434.         }
  435.     }
  436.  
  437.     /**
  438.      * Write a line of data to the socket, followed by a trailing newline.
  439.      *
  440.      * @param string $data Data to write
  441.      *
  442.      * @access public
  443.      * @return mixed fwrite() result, or PEAR_Error when not connected
  444.      */
  445.     function writeLine($data)
  446.     {
  447.         if (!is_resource($this->fp)) {
  448.             return $this->raiseError('not connected');
  449.         }
  450.  
  451.         return fwrite($this->fp$data $this->newline);
  452.     }
  453.  
  454.     /**
  455.      * Tests for end-of-file on a socket descriptor.
  456.      *
  457.      * Also returns true if the socket is disconnected.
  458.      *
  459.      * @access public
  460.      * @return bool 
  461.      */
  462.     function eof()
  463.     {
  464.         return (!is_resource($this->fp|| feof($this->fp));
  465.     }
  466.  
  467.     /**
  468.      * Reads a byte of data
  469.      *
  470.      * @access public
  471.      * @return byte of data from the socket, or a PEAR_Error if
  472.      *          not connected.
  473.      */
  474.     function readByte()
  475.     {
  476.         if (!is_resource($this->fp)) {
  477.             return $this->raiseError('not connected');
  478.         }
  479.  
  480.         return ord(@fread($this->fp1));
  481.     }
  482.  
  483.     /**
  484.      * Reads a word of data
  485.      *
  486.      * @access public
  487.      * @return word of data from the socket, or a PEAR_Error if
  488.      *          not connected.
  489.      */
  490.     function readWord()
  491.     {
  492.         if (!is_resource($this->fp)) {
  493.             return $this->raiseError('not connected');
  494.         }
  495.  
  496.         $buf @fread($this->fp2);
  497.         return (ord($buf[0](ord($buf[1]<< 8));
  498.     }
  499.  
  500.     /**
  501.      * Reads an int of data
  502.      *
  503.      * @access public
  504.      * @return integer  1 int of data from the socket, or a PEAR_Error if
  505.      *                   not connected.
  506.      */
  507.     function readInt()
  508.     {
  509.         if (!is_resource($this->fp)) {
  510.             return $this->raiseError('not connected');
  511.         }
  512.  
  513.         $buf @fread($this->fp4);
  514.         return (ord($buf[0](ord($buf[1]<< 8+
  515.                 (ord($buf[2]<< 16(ord($buf[3]<< 24));
  516.     }
  517.  
  518.     /**
  519.      * Reads a zero-terminated string of data
  520.      *
  521.      * @access public
  522.      * @return string, or a PEAR_Error if
  523.      *          not connected.
  524.      */
  525.     function readString()
  526.     {
  527.         if (!is_resource($this->fp)) {
  528.             return $this->raiseError('not connected');
  529.         }
  530.  
  531.         $string '';
  532.         while (($char @fread($this->fp1)) != "\x00"{
  533.             $string .= $char;
  534.         }
  535.         return $string;
  536.     }
  537.  
  538.     /**
  539.      * Reads an IP Address and returns it in a dot formatted string
  540.      *
  541.      * @access public
  542.      * @return Dot formatted string, or a PEAR_Error if
  543.      *          not connected.
  544.      */
  545.     function readIPAddress()
  546.     {
  547.         if (!is_resource($this->fp)) {
  548.             return $this->raiseError('not connected');
  549.         }
  550.  
  551.         $buf @fread($this->fp4);
  552.         return sprintf('%d.%d.%d.%d'ord($buf[0])ord($buf[1]),
  553.                        ord($buf[2])ord($buf[3]));
  554.     }
  555.  
  556.     /**
  557.      * Read until either the end of the socket or a newline, whichever
  558.      * comes first. Strips the trailing newline from the returned data.
  559.      *
  560.      * @access public
  561.      * @return All available data up to a newline, without that
  562.      *          newline, or until the end of the socket, or a PEAR_Error if
  563.      *          not connected.
  564.      */
  565.     function readLine()
  566.     {
  567.         if (!is_resource($this->fp)) {
  568.             return $this->raiseError('not connected');
  569.         }
  570.  
  571.         $line '';
  572.  
  573.         $timeout time($this->timeout;
  574.  
  575.         while (!feof($this->fp&& (!$this->timeout || time($timeout)) {
  576.             $line .= @fgets($this->fp$this->lineLength);
  577.             if (substr($line-1== "\n"{
  578.                 return rtrim($line$this->newline);
  579.             }
  580.         }
  581.         return $line;
  582.     }
  583.  
  584.     /**
  585.      * Read until the socket closes, or until there is no more data in
  586.      * the inner PHP buffer. If the inner buffer is empty, in blocking
  587.      * mode we wait for at least 1 byte of data. Therefore, in
  588.      * blocking mode, if there is no data at all to be read, this
  589.      * function will never exit (unless the socket is closed on the
  590.      * remote end).
  591.      *
  592.      * @access public
  593.      *
  594.      * @return string  All data until the socket closes, or a PEAR_Error if
  595.      *                  not connected.
  596.      */
  597.     function readAll()
  598.     {
  599.         if (!is_resource($this->fp)) {
  600.             return $this->raiseError('not connected');
  601.         }
  602.  
  603.         $data '';
  604.         while (!feof($this->fp)) {
  605.             $data .= @fread($this->fp$this->lineLength);
  606.         }
  607.         return $data;
  608.     }
  609.  
  610.     /**
  611.      * Runs the equivalent of the select() system call on the socket
  612.      * with a timeout specified by tv_sec and tv_usec.
  613.      *
  614.      * @param integer $state   Which of read/write/error to check for.
  615.      * @param integer $tv_sec  Number of seconds for timeout.
  616.      * @param integer $tv_usec Number of microseconds for timeout.
  617.      *
  618.      * @access public
  619.      * @return False if select fails, integer describing which of read/write/error
  620.      *          are ready, or PEAR_Error if not connected.
  621.      */
  622.     function select($state$tv_sec$tv_usec = 0)
  623.     {
  624.         if (!is_resource($this->fp)) {
  625.             return $this->raiseError('not connected');
  626.         }
  627.  
  628.         $read   = null;
  629.         $write  = null;
  630.         $except = null;
  631.         if ($state NET_SOCKET_READ{
  632.             $read[$this->fp;
  633.         }
  634.         if ($state NET_SOCKET_WRITE{
  635.             $write[$this->fp;
  636.         }
  637.         if ($state NET_SOCKET_ERROR{
  638.             $except[$this->fp;
  639.         }
  640.         if (false === ($sr stream_select($read$write$except,
  641.                                           $tv_sec$tv_usec))) {
  642.             return false;
  643.         }
  644.  
  645.         $result = 0;
  646.         if (count($read)) {
  647.             $result |= NET_SOCKET_READ;
  648.         }
  649.         if (count($write)) {
  650.             $result |= NET_SOCKET_WRITE;
  651.         }
  652.         if (count($except)) {
  653.             $result |= NET_SOCKET_ERROR;
  654.         }
  655.         return $result;
  656.     }
  657.  
  658.     /**
  659.      * Turns encryption on/off on a connected socket.
  660.      *
  661.      * @param bool    $enabled Set this parameter to true to enable encryption
  662.      *                          and false to disable encryption.
  663.      * @param integer $type    Type of encryption. See stream_socket_enable_crypto()
  664.      *                          for values.
  665.      *
  666.      * @see    http://se.php.net/manual/en/function.stream-socket-enable-crypto.php
  667.      * @access public
  668.      * @return false on error, true on success and 0 if there isn't enough data
  669.      *          and the user should try again (non-blocking sockets only).
  670.      *          A PEAR_Error object is returned if the socket is not
  671.      *          connected
  672.      */
  673.     function enableCrypto($enabled$type)
  674.     {
  675.         if (version_compare(phpversion()"5.1.0"">=")) {
  676.             if (!is_resource($this->fp)) {
  677.                 return $this->raiseError('not connected');
  678.             }
  679.             return @stream_socket_enable_crypto($this->fp$enabled$type);
  680.         else {
  681.             $msg 'Net_Socket::enableCrypto() requires php version >= 5.1.0';
  682.             return $this->raiseError($msg);
  683.         }
  684.     }
  685.  
  686. }

Documentation generated on Fri, 24 May 2013 19:30:02 +0000 by phpDocumentor 1.4.3. PEAR Logo Copyright © PHP Group 2004.