ここの情報は古いです。ご理解頂いた上でお取り扱いください。

source: OpenPNE/branches/ebihara/prj_pnebiz/lib/include/Net/Socket.php @ 557

Last change on this file since 557 was 557, checked in by ebihara, 14 years ago

create prj_pnebiz

File size: 15.0 KB
Line 
1<?php
2//
3// +----------------------------------------------------------------------+
4// | PHP Version 4                                                        |
5// +----------------------------------------------------------------------+
6// | Copyright (c) 1997-2003 The PHP Group                                |
7// +----------------------------------------------------------------------+
8// | This source file is subject to version 2.0 of the PHP license,       |
9// | that is bundled with this package in the file LICENSE, and is        |
10// | available at through the world-wide-web at                           |
11// | http://www.php.net/license/2_02.txt.                                 |
12// | If you did not receive a copy of the PHP license and are unable to   |
13// | obtain it through the world-wide-web, please send a note to          |
14// | license@php.net so we can mail you a copy immediately.               |
15// +----------------------------------------------------------------------+
16// | Authors: Stig Bakken <ssb@php.net>                                   |
17// |          Chuck Hagenbuch <chuck@horde.org>                           |
18// +----------------------------------------------------------------------+
19//
20// $Id: Socket.php,v 1.24 2005/02/03 20:40:16 chagenbu Exp $
21
22require_once 'PEAR.php';
23
24define('NET_SOCKET_READ',  1);
25define('NET_SOCKET_WRITE', 2);
26define('NET_SOCKET_ERROR', 3);
27
28/**
29 * Generalized Socket class.
30 *
31 * @version 1.1
32 * @author Stig Bakken <ssb@php.net>
33 * @author Chuck Hagenbuch <chuck@horde.org>
34 */
35class Net_Socket extends PEAR {
36
37    /**
38     * Socket file pointer.
39     * @var resource $fp
40     */
41    var $fp = null;
42
43    /**
44     * Whether the socket is blocking. Defaults to true.
45     * @var boolean $blocking
46     */
47    var $blocking = true;
48
49    /**
50     * Whether the socket is persistent. Defaults to false.
51     * @var boolean $persistent
52     */
53    var $persistent = false;
54
55    /**
56     * The IP address to connect to.
57     * @var string $addr
58     */
59    var $addr = '';
60
61    /**
62     * The port number to connect to.
63     * @var integer $port
64     */
65    var $port = 0;
66
67    /**
68     * Number of seconds to wait on socket connections before assuming
69     * there's no more data. Defaults to no timeout.
70     * @var integer $timeout
71     */
72    var $timeout = false;
73
74    /**
75     * Number of bytes to read at a time in readLine() and
76     * readAll(). Defaults to 2048.
77     * @var integer $lineLength
78     */
79    var $lineLength = 2048;
80
81    /**
82     * Connect to the specified port. If called when the socket is
83     * already connected, it disconnects and connects again.
84     *
85     * @param string  $addr        IP address or host name.
86     * @param integer $port        TCP port number.
87     * @param boolean $persistent  (optional) Whether the connection is
88     *                             persistent (kept open between requests
89     *                             by the web server).
90     * @param integer $timeout     (optional) How long to wait for data.
91     * @param array   $options     See options for stream_context_create.
92     *
93     * @access public
94     *
95     * @return boolean | PEAR_Error  True on success or a PEAR_Error on failure.
96     */
97    function connect($addr, $port = 0, $persistent = null, $timeout = null, $options = null)
98    {
99        if (is_resource($this->fp)) {
100            @fclose($this->fp);
101            $this->fp = null;
102        }
103
104        if (!$addr) {
105            return $this->raiseError('$addr cannot be empty');
106        } elseif (strspn($addr, '.0123456789') == strlen($addr) ||
107                  strstr($addr, '/') !== false) {
108            $this->addr = $addr;
109        } else {
110            $this->addr = @gethostbyname($addr);
111        }
112
113        $this->port = $port % 65536;
114
115        if ($persistent !== null) {
116            $this->persistent = $persistent;
117        }
118
119        if ($timeout !== null) {
120            $this->timeout = $timeout;
121        }
122
123        $openfunc = $this->persistent ? 'pfsockopen' : 'fsockopen';
124        $errno = 0;
125        $errstr = '';
126        if ($options && function_exists('stream_context_create')) {
127            if ($this->timeout) {
128                $timeout = $this->timeout;
129            } else {
130                $timeout = 0;
131            }
132            $context = stream_context_create($options);
133            $fp = @$openfunc($this->addr, $this->port, $errno, $errstr, $timeout, $context);
134        } else {
135            if ($this->timeout) {
136                $fp = @$openfunc($this->addr, $this->port, $errno, $errstr, $this->timeout);
137            } else {
138                $fp = @$openfunc($this->addr, $this->port, $errno, $errstr);
139            }
140        }
141
142        if (!$fp) {
143            return $this->raiseError($errstr, $errno);
144        }
145
146        $this->fp = $fp;
147
148        return $this->setBlocking($this->blocking);
149    }
150
151    /**
152     * Disconnects from the peer, closes the socket.
153     *
154     * @access public
155     * @return mixed true on success or an error object otherwise
156     */
157    function disconnect()
158    {
159        if (!is_resource($this->fp)) {
160            return $this->raiseError('not connected');
161        }
162
163        @fclose($this->fp);
164        $this->fp = null;
165        return true;
166    }
167
168    /**
169     * Find out if the socket is in blocking mode.
170     *
171     * @access public
172     * @return boolean  The current blocking mode.
173     */
174    function isBlocking()
175    {
176        return $this->blocking;
177    }
178
179    /**
180     * Sets whether the socket connection should be blocking or
181     * not. A read call to a non-blocking socket will return immediately
182     * if there is no data available, whereas it will block until there
183     * is data for blocking sockets.
184     *
185     * @param boolean $mode  True for blocking sockets, false for nonblocking.
186     * @access public
187     * @return mixed true on success or an error object otherwise
188     */
189    function setBlocking($mode)
190    {
191        if (!is_resource($this->fp)) {
192            return $this->raiseError('not connected');
193        }
194
195        $this->blocking = $mode;
196        socket_set_blocking($this->fp, $this->blocking);
197        return true;
198    }
199
200    /**
201     * Sets the timeout value on socket descriptor,
202     * expressed in the sum of seconds and microseconds
203     *
204     * @param integer $seconds  Seconds.
205     * @param integer $microseconds  Microseconds.
206     * @access public
207     * @return mixed true on success or an error object otherwise
208     */
209    function setTimeout($seconds, $microseconds)
210    {
211        if (!is_resource($this->fp)) {
212            return $this->raiseError('not connected');
213        }
214
215        return socket_set_timeout($this->fp, $seconds, $microseconds);
216    }
217
218    /**
219     * Returns information about an existing socket resource.
220     * Currently returns four entries in the result array:
221     *
222     * <p>
223     * timed_out (bool) - The socket timed out waiting for data<br>
224     * blocked (bool) - The socket was blocked<br>
225     * eof (bool) - Indicates EOF event<br>
226     * unread_bytes (int) - Number of bytes left in the socket buffer<br>
227     * </p>
228     *
229     * @access public
230     * @return mixed Array containing information about existing socket resource or an error object otherwise
231     */
232    function getStatus()
233    {
234        if (!is_resource($this->fp)) {
235            return $this->raiseError('not connected');
236        }
237
238        return socket_get_status($this->fp);
239    }
240
241    /**
242     * Get a specified line of data
243     *
244     * @access public
245     * @return $size bytes of data from the socket, or a PEAR_Error if
246     *         not connected.
247     */
248    function gets($size)
249    {
250        if (!is_resource($this->fp)) {
251            return $this->raiseError('not connected');
252        }
253
254        return @fgets($this->fp, $size);
255    }
256
257    /**
258     * Read a specified amount of data. This is guaranteed to return,
259     * and has the added benefit of getting everything in one fread()
260     * chunk; if you know the size of the data you're getting
261     * beforehand, this is definitely the way to go.
262     *
263     * @param integer $size  The number of bytes to read from the socket.
264     * @access public
265     * @return $size bytes of data from the socket, or a PEAR_Error if
266     *         not connected.
267     */
268    function read($size)
269    {
270        if (!is_resource($this->fp)) {
271            return $this->raiseError('not connected');
272        }
273
274        return @fread($this->fp, $size);
275    }
276
277    /**
278     * Write a specified amount of data.
279     *
280     * @param string  $data       Data to write.
281     * @param integer $blocksize  Amount of data to write at once.
282     *                            NULL means all at once.
283     *
284     * @access public
285     * @return mixed true on success or an error object otherwise
286     */
287    function write($data, $blocksize = null)
288    {
289        if (!is_resource($this->fp)) {
290            return $this->raiseError('not connected');
291        }
292
293        if (is_null($blocksize) && !OS_WINDOWS) {
294            return fwrite($this->fp, $data);
295        } else {
296            if (is_null($blocksize)) {
297                $blocksize = 1024;
298            }
299
300            $pos = 0;
301            $size = strlen($data);
302            while ($pos < $size) {
303                $written = @fwrite($this->fp, substr($data, $pos, $blocksize));
304                if ($written === false) {
305                    return false;
306                }
307                $pos += $written;
308            }
309
310            return $pos;
311        }
312    }
313
314    /**
315     * Write a line of data to the socket, followed by a trailing "\r\n".
316     *
317     * @access public
318     * @return mixed fputs result, or an error
319     */
320    function writeLine($data)
321    {
322        if (!is_resource($this->fp)) {
323            return $this->raiseError('not connected');
324        }
325
326        return fwrite($this->fp, $data . "\r\n");
327    }
328
329    /**
330     * Tests for end-of-file on a socket descriptor.
331     *
332     * @access public
333     * @return bool
334     */
335    function eof()
336    {
337        return (is_resource($this->fp) && feof($this->fp));
338    }
339
340    /**
341     * Reads a byte of data
342     *
343     * @access public
344     * @return 1 byte of data from the socket, or a PEAR_Error if
345     *         not connected.
346     */
347    function readByte()
348    {
349        if (!is_resource($this->fp)) {
350            return $this->raiseError('not connected');
351        }
352
353        return ord(@fread($this->fp, 1));
354    }
355
356    /**
357     * Reads a word of data
358     *
359     * @access public
360     * @return 1 word of data from the socket, or a PEAR_Error if
361     *         not connected.
362     */
363    function readWord()
364    {
365        if (!is_resource($this->fp)) {
366            return $this->raiseError('not connected');
367        }
368
369        $buf = @fread($this->fp, 2);
370        return (ord($buf[0]) + (ord($buf[1]) << 8));
371    }
372
373    /**
374     * Reads an int of data
375     *
376     * @access public
377     * @return integer  1 int of data from the socket, or a PEAR_Error if
378     *                  not connected.
379     */
380    function readInt()
381    {
382        if (!is_resource($this->fp)) {
383            return $this->raiseError('not connected');
384        }
385
386        $buf = @fread($this->fp, 4);
387        return (ord($buf[0]) + (ord($buf[1]) << 8) +
388                (ord($buf[2]) << 16) + (ord($buf[3]) << 24));
389    }
390
391    /**
392     * Reads a zero-terminated string of data
393     *
394     * @access public
395     * @return string, or a PEAR_Error if
396     *         not connected.
397     */
398    function readString()
399    {
400        if (!is_resource($this->fp)) {
401            return $this->raiseError('not connected');
402        }
403
404        $string = '';
405        while (($char = @fread($this->fp, 1)) != "\x00")  {
406            $string .= $char;
407        }
408        return $string;
409    }
410
411    /**
412     * Reads an IP Address and returns it in a dot formated string
413     *
414     * @access public
415     * @return Dot formated string, or a PEAR_Error if
416     *         not connected.
417     */
418    function readIPAddress()
419    {
420        if (!is_resource($this->fp)) {
421            return $this->raiseError('not connected');
422        }
423
424        $buf = @fread($this->fp, 4);
425        return sprintf("%s.%s.%s.%s", ord($buf[0]), ord($buf[1]),
426                       ord($buf[2]), ord($buf[3]));
427    }
428
429    /**
430     * Read until either the end of the socket or a newline, whichever
431     * comes first. Strips the trailing newline from the returned data.
432     *
433     * @access public
434     * @return All available data up to a newline, without that
435     *         newline, or until the end of the socket, or a PEAR_Error if
436     *         not connected.
437     */
438    function readLine()
439    {
440        if (!is_resource($this->fp)) {
441            return $this->raiseError('not connected');
442        }
443
444        $line = '';
445        $timeout = time() + $this->timeout;
446        while (!feof($this->fp) && (!$this->timeout || time() < $timeout)) {
447            $line .= @fgets($this->fp, $this->lineLength);
448            if (substr($line, -1) == "\n") {
449                return rtrim($line, "\r\n");
450            }
451        }
452        return $line;
453    }
454
455    /**
456     * Read until the socket closes, or until there is no more data in
457     * the inner PHP buffer. If the inner buffer is empty, in blocking
458     * mode we wait for at least 1 byte of data. Therefore, in
459     * blocking mode, if there is no data at all to be read, this
460     * function will never exit (unless the socket is closed on the
461     * remote end).
462     *
463     * @access public
464     *
465     * @return string  All data until the socket closes, or a PEAR_Error if
466     *                 not connected.
467     */
468    function readAll()
469    {
470        if (!is_resource($this->fp)) {
471            return $this->raiseError('not connected');
472        }
473
474        $data = '';
475        while (!feof($this->fp)) {
476            $data .= @fread($this->fp, $this->lineLength);
477        }
478        return $data;
479    }
480
481    /**
482     * Runs the equivalent of the select() system call on the socket
483     * with a timeout specified by tv_sec and tv_usec.
484     *
485     * @param integer $state    Which of read/write/error to check for.
486     * @param integer $tv_sec   Number of seconds for timeout.
487     * @param integer $tv_usec  Number of microseconds for timeout.
488     *
489     * @access public
490     * @return False if select fails, integer describing which of read/write/error
491     *         are ready, or PEAR_Error if not connected.
492     */
493    function select($state, $tv_sec, $tv_usec = 0)
494    {
495        if (!is_resource($this->fp)) {
496            return $this->raiseError('not connected');
497        }
498
499        $read = null;
500        $write = null;
501        $except = null;
502        if ($state & NET_SOCKET_READ) {
503            $read[] = $this->fp;
504        }
505        if ($state & NET_SOCKET_WRITE) {
506            $write[] = $this->fp;
507        }
508        if ($state & NET_SOCKET_ERROR) {
509            $except[] = $this->fp;
510        }
511        if (false === ($sr = stream_select($read, $write, $except, $tv_sec, $tv_usec))) {
512            return false;
513        }
514
515        $result = 0;
516        if (count($read)) {
517            $result |= NET_SOCKET_READ;
518        }
519        if (count($write)) {
520            $result |= NET_SOCKET_WRITE;
521        }
522        if (count($except)) {
523            $result |= NET_SOCKET_ERROR;
524        }
525        return $result;
526    }
527
528}
Note: See TracBrowser for help on using the repository browser.