Rogério Lino

PHP: Socket Class

Por Rogério Alencar Lino Filho | 22 de abril de 2010 | 3 Comentários

Muitas linguagens oferecem suporte a Sockets, e com PHP não é diferente, porém a falta de orientação a objetos nas funções do PHP pode ser um inconveniente para algumas pessoas. E como eu me incluo entre essas pessoas, quando precisei utilizar sockets em PHP acabei criando um classe para englobar essas funções soltas e fornecer tratamento a erros.

/**
 * Copyright 2010 Rogerio Alencar Lino Filho
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Socket
 *
 * @author rogeriolino
 */
class Socket {

    private $port     = 3000;
    private $address  = "localhost";
    private $blocking = true;

    private $buffer   = 2048;
    private $backlog  = 5;

    private $type     = SOCK_STREAM;
    private $family   = AF_INET;
    private $protocol = SOL_TCP;

    private $resource;

    /**
     * Socket constructor
     * @param  $resource
     */
    public function  __construct($resource = null) {
        if ($resource == null) {
            $this->resource = socket_create($this->family, $this->type, $this->protocol);
        } else {
            $this->resource = $resource;
        }
    }

    /**
     * Returns the socket port
     * @return int
     */
    public function get_port() {
        return $this->port;
    }

    /**
     * Define the socket port
     * @param int $port
     */
    public function set_port($port) {
        $this->port = $port;
    }

    /**
     *
     * @return string
     */
    public function get_address() {
        return $this->address;
    }

    public function set_address($address) {
        $this->address = $address;
    }

    /**
     * Returns if the socket is blocking mode
     * @return boolean
     */
    public function is_blocking() {
        return $this->blocking;
    }

    /**
     * Defines whether the socket is blocking or nonblocking mode
     * @param boolean $block
     */
    public function set_blocking($blocking) {
        $this->blocking = ($blocking == true);
        $this->update_blocking_mode();
    }

    /**
     * Returns the socket communication type
     * @return int
     */
    public function get_type() {
        return $this->type;
    }

    /**
     * Define the socket communication type
     * @param int $type
     */
    public function set_type($type) {
        if ($type == SOCK_STREAM || $type == SOCK_DGRAM || $type == SOCK_SEQPACKET || $type == SOCK_RAW || $type == SOCK_RDM) {
            $this->type = $type;
        } else {
            throw new Socket_Exception("Invalid socket communication type");
        }
    }

    /**
     * Returns the socket protocol family
     * @return int
     */
    public function get_family() {
        return $this->family;
    }

    /**
     * Define the socket protocol family
     * @param int $family
     */
    public function set_family($family) {
        if ($family == AF_INET || $family == AF_INET6 || $family == AF_UNIX) {
            $this->family = $family;
        } else {
            throw new Socket_Exception("Invalid socket protocol family");
        }
    }

    /**
     * Returns the socket protocol
     * @return int
     */
    public function get_protocol() {
        return $this->protocol;
    }

    /**
     * Define the socket protocol, must be compatible whit the protocol family
     * @param int $protocol
     */
    public function set_protocol($protocol) {
        if ($protocol == SOL_TCP || $protocol == SOL_UDP || $protocol == SOL_SOCKET) {
            $this->protocol = $protocol;
        } else {
            throw new Socket_Exception("Invalid socket protocol");
        }
    }

    /**
     * Binds to a socket
     * @throws Socket_Exception
     */
    public function bind() {
        if (socket_bind($this->resource, $this->address, $this->port) === false) {
            throw new Socket_Exception("Socket bind failed: " . $this->error());
        }
    }

    /**
     * Listens for a connection on a socket
     * @throws Socket_Exception
     */
    public function listen() {
        if (socket_listen($this->resource, $this->backlog) === false) {
            throw new Socket_Exception("Socket listen failed: " . $this->error());
        }
    }

    /**
     * Accepts a connection
     * @throws Socket_Exception
     * @return Socket
     */
    public function accept() {
        $sock = socket_accept($this->resource);
        if ($sock === false) {
            throw new Socket_Exception("Socket accept failed: " . $this->error());
        }
        return new Socket($sock);
    }

    /**
     * Reads data from the connected socket
     * @return string
     */
    public function read() {
        $data = "";
        while (($m = socket_read($this->resource, $this->buffer)) != "") {
            $data .= $m;
        }
        return $data;
    }

    /**
     * Write the data to connected socket
     * @param string $message
     */
    public function write($data) {
        socket_write($this->resource, $data, strlen($data));
    }

    /**
     * Initiates a connection on a socket
     * @throws Socket_Exception
     * @return boolean
     */
    public function connect() {
        try {
            return socket_connect($this->resource, $this->address, $this->port);
        } catch (Socket_Exception $e) {
            return false;
        }
    }

    /**
     * Close the socket connection
     */
    public function close() {
        socket_close($this->resource);
    }

    private function update_blocking_mode() {
        if ($this->blocking) {
            socket_set_block($this->resource);
        } else {
            socket_set_nonblock($this->resource);
        }
    }

    private function error() {
        return socket_strerror(socket_last_error($this->resource));
    }

}

Classe para as exceções:

/**
 * Copyright 2010 Rogerio Alencar Lino Filho
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Socket_Exception
 *
 * @author rogeriolino
 */
class Socket_Exception extends Exception {

    public function  __construct($message, $code = 0, $previous = null) {
        $this->message = $message;
        $this->code = $code;
        $this->message = $previous;
    }

}

Espero que seja de bom aproveito.

Posts relacionados:
  1. PHP: Annotations
Tags: , , , , , , , ,