Sockets em PHPIntroduçãoSeguindo a lógica do artigo Introdução a Sockets, agora mostrarei a vocês como utilizá-los em PHP.
Se for o seu caso, tire da cabeça a idéia de que PHP é utilizado apenas na criação de sites.
Como utilizarComo eu disse no artigo de introdução, o processo para fazer um pedido é o seguinte:
1 - Cria o Socket
2 - Conecta o Socket no destino
3 - Faz o pedido
Segue abaixo a função utilizada para criar o Socket:
resource socket_create ( int $domain , int $type , int $protocol )
O resource é o valor que a função retorna.
O parâmetro int $domain Ele pode ter três valores, que são:
AF_INET, AF_INET6, e AF_UNIX
AF_INET é a família de protocolo que utiliza TCP e UDP para transferência de dados, IPv4.
AF_INET6 só tem a diferença de ser IPv6.
AF_UNIX é utilizado para comunicações locais.
O parâmetro typeSeleciona o tipo de comunicação que vai ser utilizado, eles podem ser:
SOCK_STREAM,SOCK_DGRAM,SOCK_SEQPACKET,SOCK_RAW,SOCK_RDM.
Nesse artigo, utilizaremos apenas SOCK_STREAM, em que o TCP se basea.
O parâmetro protocolEle configura o protocolo que será utilizado dentro da família que foi especificada no parâmetro domain.
As opções são:
icmp,udp,tcp
Nesse artigo abordaremos apenas TCP.
Você pode utilizar as constantes SOL_TCP e SOL_UDP para passar o protocolo, ou deve utilizar a função getprotobyname() para pegar o correspondente numérico de um protocolo, exemplo : getprotobyname('tcp').
Agora que já conhecemos o básico, podemos criar um Socket:
$sk = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
O próximo passo é utilizar o Socket criado para se conectar em um destino, segue o protótipo da função que será utilizada com esse objetivo:
bool socket_connect ( resource $socket , string $address [, int $port ] )
bool é o valor retornado pela função, ou seja, true ou false.
O primeiro parâmetro, resource $socket, é o socket que criamos.
no caso, é o $sk.
O parâmetro string $address, é o destino onde nos conectaremos.
O parâmetro int $port é utilizado apenas quando estamos trabalhando com a família AF_INET, e especifica a qual porta nos conectaremos no destino.
Então, segue a conexão com o host remoto:
$err = socket_connect($sk, 'www.darkers.com.br', 80);
Depois que nos conectarmos, o próximo passo é fazer o pedido de uma página qualquer.
Como estamos trabalhando com o Socket puro, deveremos escrever inclusive a requisição da página.
O pedido pode ser esse:
$pedido = "GET / HTTP/1.1 \r\n";
$pedido .= "Host: www.darkers.com.br (http://www.darkers.com.br) \r\n\r\n";
GET / pede para o Darkers nos mandar a página inicial.
HTTP/1.1 diz qual versão do protocolo http estamos utilizando.
\r\n faz com que haja uma nova linha, ela faz parte da especificação RFC 2616.
Host: www.darkers.com.br (http://www.darkers.com.br) diz ao servidor para qual host estamos enviando a requisição.
\r\n\r\n é devido à especificação, todo request deve terminar com duas novas linhas.
E agora, temos que mandar alguém enviar esse pedido, e quem vai fazer isso é a função:
int socket_write ( resource $socket , string $buffer [, int $length ] )
Como podem observar, a função retorna int, que significa a quantidade de bytes que foram escritos com sucesso no socket que foi passado pelo parâmetro resource $socket. Se um erro acontecer, a função retorna false.
O parâmetro string $buffer espeficica a string que será escrita, e int length que é opnicional, envia o tamanho do buffer.
Sendo assim, segue a utilização em conjunto com nossas criações anteriores:
$err = socket_write($sk,$pedido, strlen($pedido));
Pronto! Fizemos o pedido =]
O que eu recomendo agora, é que você faça o download de um sniffer e utilize-o para analisar a resposta do servidor.
Ele é útil não somente para ver a resposta do servidor, mas também para ver se você está mandando a requisição corretamente.
Espero que esteja tudo certo ai com o seu socket, antes de continuarmos.
Faça um echo $err para verificar quantos bytes foram escritos.
Caso tenha acontecido algum erro, entre em contato.
Agora, vamos falar do recebimento das respostas do socket.
A função utilizada é:
string socket_read ( resource $socket , int $length [, int $type ] )
A string retornada é a mesma que foi lida.
O parâmetro resource $socket, é o socket onde escreveremos, no caso, oque criamos, que foi $sk.
int $length especifica a quantidade de bytes a ser lida.
Você também pode especificar o parâmetro type para ser PHP_NORMAL_READ, assim a leitura vai parar quando encontrar o total de bytes especificado em length, ou um caractere de nova linha (\n ou \r).
Caso aconteça algum erro, o valor retornado por essa função será false.
No nosso exemplo podemos utilizar:
$dados = socket_read($sk,4000,PHP_NORMAL_READ);
E fazer um echo para mostrar os dados:
echo $dados;
Pronto! é só isso

Mas, fazendo da maneira acima, você vai ler apenas até quando a função encontrar uma nova linha (\n ou \r).
Então, torna-se necessário a utilização do while, por exemplo:
while($dados = socket_read($sk,4000,PHP_NORMAL_READ)) {
echo $dados;
}
Agora você vai lê todos os dados que estiverem no buffer, ou seja, todos os dados que o Darkers te respondeu.
Quando executar esse script verá a página do Darkers no seu browser.
Depois de terminar a utilização do socket, deve-se finalizá-lo:
socket_close($sk);
Pronto!
O código completo fica assim:
$sk = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
$err = socket_connect($sk, 'www.darkers.com.br', 80);
$pedido = "GET / HTTP/1.1 \r\n";
$pedido .= "Host: www.darkers.com.br (http://www.darkers.com.br) \r\n\r\n";
$err = socket_write($sk,$pedido, strlen($pedido));
while($dados = socket_read($sk,4000,PHP_NORMAL_READ)) {
echo $dados;
}
socket_close($sk);
?>
Repare bem que pegamos tudo que foi retornado, inclusive os headers.
Até a parte 2.
Aguardando a parte II.
Tks branco.