Search code examples
phpsocketstimeoutfgets

Php - fgets() reading with socket, still not working properly


I've spent a lot of time on this fgets() problems without any success until now. I'm receiving data from different sources through a HTTP socket. It worked fine until now that I have a lot more different sources.

My goal is just to get rid of the execution timeout of php, just know that it timed out after 15 seconds but go on with the next source.

Here is my small piece of code:

//This is just from php.net, found out that it works pretty good
$time = time();
while (!($temp = fsockopen($host, $port, $errNo, $errMessage, $timeout)))
{
    if ((time() - $time) >= $timeout)
    {
        socket_close($temp);
        return false;
    }
    sleep(1);
}

    //If PHP returns an error
 if (!($temp)) {
    echo 'Socket could not be opened.<br/>';
    return false;
}

$return = "";

if (!fwrite($temp, $out)) {
    print_r(error_get_last());
    return false;
}

    //Timeout set to 15 seconds
    stream_set_blocking($temp, 0);
    $start = time();

    while ((time() < ($start + 15))) {

        //(Last lines always finishes like this)
        if (substr(trim($return),-9) == '"id":"1"}') {
            break;
        } else {
            $return .= fgets($temp, 512);
        }
    }
    fclose($temp);

After some testing I found out that a non-blocking socket gives way better results for this code, however it is still blocking after data has been received for 4 sources. (I tried to change the order so it is not source-dependent)

I tried to use stream_set_timeout($temp) and check the state of the flag in the loop but it doesn't change a thing.

EDIT: I forgot to mention it, but the script is stopping (PHP execution timeout of 30 seconds) at the line with fgets().

Any clues?

Cheers!


Solution

  • The documentation of the length parameter to fgets():

    Reading ends when length - 1 bytes have been read, or a newline (which is included in the return value), or an EOF (whichever comes first). If no length is specified, it will keep reading from the stream until it reaches the end of the line.

    None of these conditions will be met in your case, which will let the script wait indefinitely on input.

    To make use of the socket timeout set by stream_set_timeout() you can use fread() instead of fgets(), which will honor the set timeout. The only difference with fgets() is that fread() doesn't fetch a line at a time, but the whole length number of bytes.