W3docs

Função PHP socket_set_blocking(): Tudo o que Você Precisa Saber

Aprenda a usar socket_set_blocking() no PHP, suas alternativas modernas e como controlar modos bloqueante e não bloqueante em sockets e streams.

Ao escrever código de rede em PHP, muitas vezes é necessário controlar se uma chamada de I/O aguarda pelos dados (modo bloqueante) ou retorna imediatamente (modo não bloqueante). A função socket_set_blocking() era o alias histórico para definir esse modo. Ela foi descontinuada no PHP 8.1 e não deve ser usada em código novo.

O problema é que a substituição correta depende do tipo de conexão que você possui, e é aqui que muitos guias erram:

  • Se você usou a extensão Sockets (socket_create(), que retorna um objeto Socket), use socket_set_nonblock() e socket_set_block().
  • Se você usou um stream (fsockopen() ou stream_socket_client(), que retornam um recurso de stream), use stream_set_blocking().

socket_set_blocking() era na verdade um alias de stream_set_blocking(), portanto só funcionava com recursos de stream — nunca com objetos Socket. Essa distinção é a chave para evitar um TypeError em tempo de execução.

Modo Bloqueante vs. Não Bloqueante

No modo bloqueante (o padrão), uma chamada de leitura ou escrita pausa a execução do script até que a operação possa ser concluída. Um socket_read() em um socket vazio simplesmente aguarda até que os bytes cheguem.

No modo não bloqueante, a mesma chamada retorna imediatamente. Se nenhum dado estiver disponível, ela retorna um resultado vazio (ou false) em vez de aguardar. Isso permite que um único script gerencie muitas conexões ou permaneça responsivo — ao custo de você ter que verificar periodicamente se os dados realmente chegaram.

Use o modo bloqueante quando…Use o modo não bloqueante quando…
Você lida com uma conexão por vezVocê atende muitos clientes em um único loop
A simplicidade importa mais que o desempenhoO script precisa permanecer responsivo
Uma requisição/resposta curta e previsívelVocê implementa seu próprio loop de polling/eventos

Definindo o Modo em um Objeto Socket

Se você criou a conexão com a extensão Sockets, use socket_set_nonblock() e socket_set_block():

socket_set_nonblock(Socket $socket): bool
socket_set_block(Socket $socket): bool

Ambas retornam true em caso de sucesso e false em caso de falha. Um exemplo completo e executável com tratamento de erros e limpeza:

<?php

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
    die("Socket creation failed: " . socket_strerror(socket_last_error()) . "\n");
}

// Switch to non-blocking mode
if (!socket_set_nonblock($socket)) {
    die("Failed to set non-blocking mode\n");
}
echo "Socket is now non-blocking.\n";

// ... perform non-blocking socket operations ...

// Switch back to blocking mode if needed
socket_set_block($socket);
echo "Socket is now blocking again.\n";

socket_close($socket);

Não chame stream_set_blocking($socket, false) em um objeto Socketsocket_create() retorna uma instância de Socket, e stream_set_blocking() só aceita um recurso de stream. Passar um Socket lança um TypeError.

Definindo o Modo em um Stream

Se você abriu a conexão com fsockopen() ou stream_socket_client(), você tem um recurso de stream e deve usar stream_set_blocking():

stream_set_blocking(resource $stream, bool $enable): bool
  • $stream: o recurso de stream a ser configurado.
  • $enable: true para modo bloqueante, false para modo não bloqueante.
<?php

$stream = stream_socket_client('tcp://example.com:80', $errno, $errstr, 5);
if ($stream === false) {
    die("Connect failed: $errstr ($errno)\n");
}

// Switch the stream to non-blocking mode
if (!stream_set_blocking($stream, false)) {
    die("Failed to set non-blocking mode\n");
}
echo "Stream is now non-blocking.\n";

fclose($stream);

Um Loop de Leitura Não Bloqueante

O modo não bloqueante só é útil se você realizar polling. Um padrão típico envia uma requisição e verifica repetidamente se há uma resposta sem travar o script:

<?php

$stream = stream_socket_client('tcp://example.com:80', $errno, $errstr, 5);
if ($stream === false) {
    die("Connect failed: $errstr ($errno)\n");
}

stream_set_blocking($stream, false);
fwrite($stream, "GET / HTTP/1.0\r\nHost: example.com\r\n\r\n");

$response = '';
$start = time();
while (!feof($stream) && time() - $start < 5) {
    $chunk = fread($stream, 8192);
    if ($chunk === '' || $chunk === false) {
        // No data yet — do other work or wait briefly
        usleep(50000); // 50 ms
        continue;
    }
    $response .= $chunk;
}

echo substr($response, 0, 15), "\n"; // e.g. "HTTP/1.1 200 OK"
fclose($stream);

A chamada usleep() evita que um loop ocupado sobrecarregue a CPU. Em produção, você normalmente substituiria esse polling manual por stream_select() para aguardar eficientemente em múltiplos streams ao mesmo tempo.

Notas de Versão

  • PHP 8.1: socket_set_blocking() foi descontinuada. Chamá-la emite um aviso de descontinuação.
  • A função era um alias de stream_set_blocking(), portanto nunca aceitou objetos Socket.
  • Para objetos Socket, socket_set_nonblock() / socket_set_block() sempre foram as chamadas corretas e continuam sendo suportadas.

Funções Relacionadas

  • socket_get_status() — inspeciona o estado de um socket, incluindo se ele está bloqueado.
  • socket_set_timeout() — controla por quanto tempo uma operação bloqueante aguarda antes de desistir.
  • PHP Streams — a API de streams mais ampla à qual stream_set_blocking() pertence.

Conclusão

Controlar o modo de bloqueio de uma conexão é essencial para construir aplicações de rede PHP responsivas. A chave é combinar a função com o tipo de conexão: use socket_set_nonblock() / socket_set_block() para objetos Socket, e stream_set_blocking() para recursos de stream. Evite a função descontinuada socket_set_blocking() em código novo e lembre-se de que o modo não bloqueante só vale a pena quando combinado com um loop de polling.

Prática

Prática
No PHP, o que a função socket_set_blocking() faz?
No PHP, o que a função socket_set_blocking() faz?
Was this page helpful?