CXVI. Funções de Socket

Introdução

A extensão socket implementa uma interface de baixo nível para funções de comunicação sockets baseadas no popular BSD sockets, disponibilizando acionar como um servidor socket ou como um cliente.

Para saber mais informações sobre sockets cliente-servidor, veja stream_socket_client(), stream_socket_server(), fsockopen(), e pfsockopen().

Quando usando estas funções, é importante relembrar que enquanto muitas delas tem nomes idênticos equivalentes em C, eles tem frequentemente declarações diferentes. Por favor tenha certeza lendo as descrições para evitar confusão.

Aqueles não familiarizados com programação usando socket podem encontrar muito material útil nas "man pages" de Unix, e há uma infinidade de tutoriais com informações usando socket em C na web, muito dos quais podem ser aplicados, com pequenas modificações, para programação usando socket em PHP. O UNIX Socket FAQ pode ser um bom começo.

Atenção

Este módulo é EXPERIMENTAL. Isso quer dizer que o comportamento neste módulo --- incluindo suas funções e seus nomes, e TUDO mais que está documentado sobre esse módulo --- poderá mudar em futuras versões do PHP, SEM QUALQUER NOTIFICAÇÃO. Esteja avisado, e use este módulo por sua própria conta e risco.

Dependências

Nenhuma biblioteca externa é necessária para compilar esta extensão.

Instalação

As funções de socket descritas aqui fazem parte de uma extensão do PHP que deve ser habilitada na hora de compilar adicionando a opção --enable-sockets à linha de comando configure.

Nota: O supoerte ao IPv6 foi acrescentado no 5.0.0.

Configurações em execução

Esta extensão não define nenhum parâmetro de configuração no php.ini.

Tipos Resource

Esta extensão não possui nenhum tipo resource.

Constantes pré-definidas

As contantes abaixo são definidas por esta extensão e somente estarão disponíveis quando a extensão foi compilada com o PHP ou carregada dinamicamente durante a execução.

AF_UNIX (integer)

AF_INET (integer)

AF_INET6 (integer)

SOCK_STREAM (integer)

SOCK_DGRAM (integer)

SOCK_RAW (integer)

SOCK_SEQPACKET (integer)

SOCK_RDM (integer)

MSG_OOB (integer)

MSG_WAITALL (integer)

MSG_PEEK (integer)

MSG_DONTROUTE (integer)

SO_DEBUG (integer)

SO_REUSEADDR (integer)

SO_KEEPALIVE (integer)

SO_DONTROUTE (integer)

SO_LINGER (integer)

SO_BROADCAST (integer)

SO_OOBINLINE (integer)

SO_SNDBUF (integer)

SO_RCVBUF (integer)

SO_SNDLOWAT (integer)

SO_RCVLOWAT (integer)

SO_SNDTIMEO (integer)

SO_RCVTIMEO (integer)

SO_TYPE (integer)

SO_ERROR (integer)

SOL_SOCKET (integer)

PHP_NORMAL_READ (integer)

PHP_BINARY_READ (integer)

SOL_TCP (integer)

SOL_UDP (integer)

Socket Errors

A extensão socket foi escrita para disponibilizar uma interface útil e poderosa para sockets BSD. Tem-se notado que as funções funcionam igualmente bem em Win32 e Unix. Quase todas as funções de sockets devem falhar sob certas condições e portanto emite uma mensagem E_WARNING descrevendo o erro. De vez em quando isso não acontece para desespero do desenvolvedor. Por exemplo a função socket_read() deve de repente emitir uma mensagem E_WARNING porque a conexão foi quebrada inesperadamente. É comum esconder as mensagens de warning com o operador @ e pegar o código de erro dentro da aplicação com a função socket_last_error(). Você deve chamar a função socket_strerror() com esse código de erro para retornar uma string descrevendo o erro. Veja sua descrição para mais informações.

Nota: A mensagem de E_WARNING gerada pela extensão socket estão em inglês dificilmente a mensagem de erro retornada ira aparecer correto dependendo da localidade padrão (LC_MESSAGES):
Warning - socket_bind() unable to bind address [98]: Die Adresse wird bereits verwendet

Exemplos

Exemplo 1. Exemplo de socket: Simples servidor TCP/IP

Este exemplo mostra uma simples troca de informações do servidor. Alterar as variáveis address e port para o conjunto da sua configuração e execução. Você deve então conectar o servidor com uma linha de comando similiar a: telnet 192.168.1.53 10000 (onde o endereço e a porta partem da sua configuração). Algo que você digitar então irá sair no lado do servidor, e mostrar isso para você. Para desconectar, digite 'quit'.

#!/usr/local/bin/php -q
<?php
error_reporting
(E_ALL);

/* Allow the script to hang around waiting for connections. */
set_time_limit (0);

/* Turn on implicit output flushing so we see what we're getting
* as it comes in. */
ob_implicit_flush ();

$address = '192.168.1.53';
$port = 10000;

if ((
$sock = socket_create (AF_INET, SOCK_STREAM, 0)) < 0) {
    echo
"socket_create() failed: reason: " . socket_strerror ($sock) . "\n";
}

if ((
$ret = socket_bind ($sock, $address, $port)) < 0) {
    echo
"socket_bind() failed: reason: " . socket_strerror ($ret) . "\n";
}

if ((
$ret = socket_listen ($sock, 5)) < 0) {
    echo
"socket_listen() failed: reason: " . socket_strerror ($ret) . "\n";
}

do {
    if ((
$msgsock = socket_accept($sock)) < 0) {
        echo
"socket_accept() failed: reason: " . socket_strerror ($msgsock) . "\n";
        break;
    }
    
/* Send instructions. */
    
$msg = "\nWelcome to the PHP Test Server. \n" .
        
"To quit, type 'quit'. To shut down the server type 'shutdown'.\n";
    
socket_write($msgsock, $msg, strlen($msg));

    do {
        if (
FALSE === ($buf = socket_read ($msgsock, 2048, PHP_NORMAL_READ))) {
            echo
"socket_read() failed: reason: " . socket_strerror ($ret) . "\n";
            break
2;
        }
        if (!
$buf = trim ($buf)) {
            continue;
        }
        if (
$buf == 'quit') {
            break;
        }
        if (
$buf == 'shutdown') {
            
socket_close ($msgsock);
            break
2;
        }
        
$talkback = "PHP: You said '$buf'.\n";
        
socket_write ($msgsock, $talkback, strlen ($talkback));
        echo
"$buf\n";
    } while (
true);
    
socket_close ($msgsock);
} while (
true);

socket_close ($sock);
?>

Exemplo 2. Exemplo de Socket: Simples cliente TCP/IP

Este exemplo mostra um simples, one-shot cliente HTTP. Isso simplesmente conecta à uma página, envia um cabeçalho de requisição, mostra a resposta, e sai.

<?php
error_reporting
(E_ALL);

echo
"<h2>TCP/IP Connection</h2>\n";

/* Get the port for the WWW service. */
$service_port = getservbyname ('www', 'tcp');

/* Get the IP address for the target host. */
$address = gethostbyname ('www.example.com');

/* Create a TCP/IP socket. */
$socket = socket_create (AF_INET, SOCK_STREAM, 0);
if (
$socket < 0) {
    echo
"socket_create() failed: reason: " . socket_strerror ($socket) . "\n";
} else {
    echo
"OK.\n";
}

echo
"Attempting to connect to '$address' on port '$service_port'...";
$result = socket_connect ($socket, $address, $service_port);
if (
$result < 0) {
    echo
"socket_connect() failed.\nReason: ($result) " . socket_strerror($result) . "\n";
} else {
    echo
"OK.\n";
}

$in = "HEAD / HTTP/1.0\r\n\r\n";
$out = '';

echo
"Sending HTTP HEAD request...";
socket_write ($socket, $in, strlen ($in));
echo
"OK.\n";

echo
"Reading response:\n\n";
while (
$out = socket_read ($socket, 2048)) {
    echo
$out;
}

echo
"Closing socket...";
socket_close ($socket);
echo
"OK.\n\n";
?>

Índice
socket_accept -- Aceita uma conexão com um socket
socket_bind -- Passa um nome para o socket
socket_clear_error -- Limpa o erro no socket ou o último código de erro
socket_close -- Fecha um socket resource
socket_connect -- Inicializa uma conexão em um socket
socket_create_listen -- Abre uma porta do socket para aceitar conexões
socket_create_pair -- Cria um par de sockets irreconhecíveis e armazena-os no fds.
socket_create -- Cria um socket (endpoint para comunicação)
socket_get_option -- Pega opções de socket para o socket
socket_getpeername --  Pergunta ao lado remoto do socket dado qual deve ser o resultado em host/port ou no endereço UNIX filesystem, dependendo deste tipo.
socket_getsockname --  Pergunta o lado local dado do socket no qual deve retornar resultados no host/port ou no endereço UNIX filesystem, dependendo do tipo.
socket_last_error -- Retorna o último erro no socket
socket_listen -- Abre escuta para uma conexão no socket
socket_read -- Lê um comprimento máximo de bytes de um socket
socket_recv -- Recebe dados de um socket conectado
socket_recvfrom -- Recebe dados de um socket, conectado ou não
socket_select --  Executa a chamada de sistema select() nos arrays dados de sockets com um timeout especificado
socket_send -- Envia dados para um socket conectado
socket_sendto -- Envia uma mensagem para o socket, se estiver conectado ou não
socket_set_block --  Configura o modo bloqueio em um socket resource
socket_set_nonblock -- Configura o modo nonblocking para o arquivo de descrição fd
socket_set_option -- Configura opções de socket para o socket
socket_shutdown -- Fecha um socket para receber, enviar dados ou ambos.
socket_strerror -- Retorna uma string descrevendo o erro do socket
socket_write -- Escreve em um socket