W3docs

Função PHP socket_set_timeout(): Tudo o Que Você Precisa Saber

Aprenda como usar socket_set_timeout() no PHP para definir um tempo limite em operações de leitura/escrita em streams e evitar bloqueios prolongados.

Quando seu script lê de uma conexão de rede, um servidor lento ou inativo pode deixar o PHP bloqueado indefinidamente, prendendo um worker e frustrando os usuários. A função socket_set_timeout() define um prazo para operações de leitura/escrita, de modo que uma conexão travada falhe rapidamente em vez de ficar suspensa. Este artigo explica exatamente o que ela controla, as armadilhas comuns e como detectar um timeout quando ele ocorre.

O Que a Função socket_set_timeout() Faz

socket_set_timeout() define o timeout para operações de E/Sfread(), fgets(), fwrite(), etc. — em um stream aberto com fsockopen() ou pfsockopen(). Se uma leitura ou escrita não for concluída dentro do prazo, a operação retorna antecipadamente e o stream é marcado como timed out (tempo esgotado).

Duas coisas que ela não faz:

  • Ela não afeta o timeout de conexão. Esse é o quinto argumento de fsockopen($host, $port, $errno, $errstr, $connectTimeout). socket_set_timeout() governa apenas a transferência de dados após a conexão ser aberta.
  • Ela não faz a chamada falhar de forma explícita. Uma leitura que atinge o timeout retorna os dados recebidos até o momento (frequentemente uma string vazia) e define um flag — você precisa inspecionar esse flag com stream_get_meta_data().

Armadilha de nomenclatura: Apesar do prefixo socket_, essa função pertence à família de streams, não à extensão Sockets. Ela funciona em recursos de fsockopen(), nunca em um recurso de socket_create(). Desde o PHP 8.0, é um alias depreciado de stream_set_timeout() — prefira esse nome em código novo.

Sintaxe

socket_set_timeout(resource $stream, int $seconds, int $microseconds = 0): bool
ParâmetroDescrição
$streamUm recurso de stream aberto retornado por fsockopen() ou pfsockopen().
$secondsO timeout em segundos inteiros.
$microsecondsTempo adicional em microssegundos (opcional, padrão 0).

Retorna true em caso de sucesso e false em caso de falha (por exemplo, se $stream não for um recurso de stream válido).

Um Exemplo Funcional

Abra uma conexão, defina um timeout de leitura de 5 segundos e verifique se uma leitura atingiu o timeout:

<?php

// Open a TCP connection to a web server.
$stream = fsockopen("www.example.com", 80, $errno, $errstr, 10);

if (!$stream) {
    echo "Connection failed: $errstr ($errno)\n";
    exit;
}

// Fail any single read/write that stalls for more than 5 seconds.
socket_set_timeout($stream, 5);

// Send a minimal HTTP request.
fwrite($stream, "GET / HTTP/1.0\r\nHost: www.example.com\r\n\r\n");

// Read the first line of the response.
$line = fgets($stream, 1024);

// Check whether that read hit the timeout.
$info = stream_get_meta_data($stream);

if ($info['timed_out']) {
    echo "Read timed out — the server was too slow.\n";
} else {
    echo "First response line: " . trim($line) . "\n";
}

fclose($stream);

O ponto-chave é a chamada a stream_get_meta_data(): o elemento timed_out é a única maneira confiável de distinguir um timeout genuíno de uma conexão que simplesmente fechou.

Leitura em Loop

Quando você lê uma resposta completa, verifique timed_out a cada iteração para que uma interrupção no meio da transferência não trunque silenciosamente seus dados:

<?php

$stream = fsockopen("www.example.com", 80, $errno, $errstr, 10);
socket_set_timeout($stream, 5);

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

$body = "";
while (!feof($stream)) {
    $chunk = fgets($stream, 4096);
    $info  = stream_get_meta_data($stream);

    if ($info['timed_out']) {
        echo "Stalled before the response finished.\n";
        break;
    }
    $body .= $chunk;
}

fclose($stream);
echo "Received " . strlen($body) . " bytes.\n";

Armadilhas Comuns

  • Tipo de recurso errado. Passar um recurso de socket_create() não tem utilidade — use stream_set_timeout() com sockets de socket_create(), ou socket_set_option() para SO_RCVTIMEO/SO_SNDTIMEO.
  • Confundir timeouts de conexão e de leitura. Um timeout longo de conexão no fsockopen() não vai protegê-lo de uma resposta lenta; você precisa de ambos.
  • Esquecer de verificar timed_out. Sem isso, uma leitura com timeout parece exatamente um fim de stream limpo, levando a dados truncados silenciosamente.

Funções Relacionadas

Conclusão

socket_set_timeout() evita que leituras e escritas lentas de rede travem seu script PHP. Lembre-se de que ela funciona em streams de fsockopen() (não na extensão Sockets), governa E/S em vez da conexão, e que você deve inspecionar o flag timed_out de stream_get_meta_data() para saber se um timeout realmente ocorreu. Em código novo, utilize seu nome moderno, stream_set_timeout().

Prática

Prática
O que a função socket_set_timeout() no PHP faz?
O que a função socket_set_timeout() no PHP faz?
Was this page helpful?