Reputation: 424
Sending some data points constantly (aiming for once a second), using an infinite loop of POST requests in PHP. The data is highly time-dependent. If there's a timeout, I don't care about the lost data, I just want to move on to the next datapoint quickly.
I originally used file_get_contents()
(with a timeout value of 1) to do this POST request, but I was having some issues where it should have been timing out and wasn't. I read a lot of questions about this and the general consensus was that the timeout on file_get_contents()
wasn't being triggered because it's a read timeout, rather than a connect timeout.
I also read that sockets have both kinds of timeout, so I changed the code to use fsockopen()
instead. A snippet is included below.
// waaaay up at the top of the file
ini_set("default_socket_timeout", 1); // set default socket connect timeout
//...
// inside the loop
echo("4...");
$url = 'othersite.ie';
$fp = fsockopen($url, 80, $errno, $errstr, 1); // connect timeout of 1
if(!$fp)
{
echo($errno .": ". $errstr);
}
else
{
echo("5...");
stream_set_timeout($fp, 1, 0); // read timeout of 1
$content = http_build_query($data); // array assembled before this snippet
fwrite($fp, "POST /some/address/at/url HTTP/1.1\r\n");
fwrite($fp, "Host: www.examplesite.ie\r\n");
fwrite($fp, "Content-Type: application/x-www-form-urlencoded\r\n");
fwrite($fp, "Content-Length: ".strlen($content)."\r\n");
fwrite($fp, "Connection: close\r\n");
fwrite($fp, "\r\n");
fwrite($fp, $content);
while(!feof($fp))
{
$result = $result . fgets($fp, 1024);
}
echo("6...");
if (empty($result))
{
echo("No result");
}
}
This didn't seem to help, though. I added some echo
statements so if I was watching the output, I could see where the delay happened, and it has been invariably between "4..." and "5...". Each delay is about ten seconds, and they don't seem to have any particular order to them. Most of the time (more than 99%) the connection works, the read works, and I get my data to the server. But it's important to at least try to eliminate those 10-second hangs. Any help appreciated.
Upvotes: 4
Views: 10850
Reputation: 424
I did eventually make some progress on this. I never found out the error, but suspected it might just be blocking on the device's overloaded hardware. To solve the problem, I created a PHP file to perform the iteration once, and placed a one-second time limit on it. Then I had another file which would loop infinitely, and constantly request the first file. Ideally, the request would fail and the loop continue on if the iteration file took too long, which was close enough to what I wanted. It was a bit hacky, but it seemed to eliminate the problem. An extremely generalised example follows.
Iteration:
<?php
set_time_limit(1);
// fsockopen() etc.
?>
Loop:
<?php
$i = 0;
for($i = 0; ; $i++)
{
file_get_contents("localhost/iteration_file.php");
}
?>
Maybe that will help somebody. Ultimately, I had to switch to cURL anyway, but this method was useful for quite some time, and very reliable.
Note: This answer reflects what I actually did, and does not claim to fulfil best practices. I don't know many best practices. You could also use the include directive to include another file, or break functionality out into methods.
Months later edit: I'm going to mark this as the answer because it did for the most part solve my problem at the time.
Upvotes: 3