Detect PHP Socket Timeouts While Copying a Stream

A socket read can stop because the peer reached end of stream, because the configured read timeout expired, or because an error occurred. After copying from a socket, inspect its metadata before treating the destination as complete. A connection timeout alone does not configure later reads.

Last updated: October 4, 2026.

<?php
$socket = stream_socket_client(
    'tcp://example.test:9000',
    $errorCode,
    $errorMessage,
    5
);

if ($socket === false) {
    throw new RuntimeException($errorMessage, $errorCode);
}

stream_set_timeout($socket, 5);
$target = fopen('php://temp', 'w+b');
$bytes = stream_copy_to_stream($socket, $target);
$meta = stream_get_meta_data($socket);

if ($meta['timed_out']) {
    throw new RuntimeException('Socket read timed out; output may be partial.');
}
if ($bytes === false) {
    throw new RuntimeException('Stream copy failed.');
}

rewind($target);
$data = stream_get_contents($target);

Check timed_out before consuming the destination. The destination may already contain bytes even when the copy ends on a timeout, so deleting, rewinding, or resuming partial output must be an explicit application decision.

Set the read timeout on the connected stream

The timeout argument to stream_socket_client() applies to connecting, not to every later read. Call stream_set_timeout() on the connected socket. PHP records a timeout in stream metadata instead of guaranteeing a warning or exception.

The stream_get_meta_data() reference documents the timed_out, eof, and blocked fields available for stream inspection.

Do not confuse a timeout with end of file

The PHP manual notes that stream_copy_to_stream() stops when a blocking socket receives no data within its stream timeout, even if EOF has not occurred. It can return false after already writing partial data to the destination.

If the protocol declares a content length or terminator, validate it too; EOF by itself may not prove that an application message is complete. Close both streams in a finally block in production code. See streaming large JSON files, PHP execution-time failures, and PHP functions and return types for related handling patterns.

Related Web Cheat Sheet guides

Sergey Kornilov

Sergey Kornilov