2013-05-03 38 views
3

不断发送一些数据点(每秒一次),在PHP中使用无限循环的POST请求。数据非常依赖于时间。如果发生超时,我不关心丢失的数据,我只想快速转到下一个数据点。fsockopen()超时有时不起作用

我最初使用file_get_contents()(超时值为1)来做这个POST请求,但我有一些问题,它应该已超时,而不是。我读了很多关于这个的问题,普遍的共识是,file_get_contents()超时没有被触发,因为它是一个读取超时,而不是一个连接超时。

我也读过,套接字有两种超时,所以我改变了代码使用fsockopen()来代替。一个片段包含在下面。

// 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"); 
     } 
    } 

这似乎并没有帮助,虽然。我添加了一些echo陈述,所以如果我正在观看输出结果,我可以看到延迟发生的位置,它总是在“4 ...”和“5 ...”之间。每个延迟大约十秒钟,而且他们似乎没有任何特定的顺序。大部分时间(超过99%)连接起作用,读取起作用,并且我将数据发送到服务器。但重要的是至少要试图消除这些10秒钟的挂起。任何帮助赞赏。

回答

3

我终于在这方面取得了一些进展。我从来没有发现错误,但怀疑它可能只是在设备的过载硬件上阻塞。为了解决这个问题,我创建了一个PHP文件来执行一次迭代,并在其上放置了一秒的时间限制。然后我有另一个无限循环的文件,并不断请求第一个文件。理想情况下,如果迭代文件花费太长时间,请求会失败,并且循环继续,这足够接近我想要的。这有点哈克,但它似乎消除了这个问题。一个非常普遍的例子如下。

迭代:

<?php 

    set_time_limit(1); 
    // fsockopen() etc. 
?> 

循环:

<?php 
    $i = 0; 
    for($i = 0; ; $i++) 
    { 
     file_get_contents("localhost/iteration_file.php"); 
    } 
?> 

也许这将帮助别人。最终,我不得不切换到cURL,但这种方法在很长一段时间内很有用,而且非常可靠。

注意:这个答案反映了我的实际情况,并且不是声称要实现最佳做法。我不知道很多最佳实践。您也可以使用include指令来包含另一个文件,或将功能分解为方法。

几个月后编辑:我打算把这个标记为答案,因为它在很大程度上解决了我当时的问题。