如何限制php脚本的传出响应速度?

时间:2010-06-24 14:11:33

标签: php file response bandwidth limiting

如何限制php脚本的传出响应速度?所以我有一个脚本在keep-alive连接中生成数据。它只是打开文件并读取它。如何限制传出速度

(现在我有这样的代码)

if(isset($_GET[FILE]))
 {
  $fileName = $_GET[FILE];
  $file =  $fileName;

  if (!file_exists($file))
  {
   print('<b>ERROR:</b> php could not find (' . $fileName . ') please check your settings.'); 
   exit();
  }
  if(file_exists($file))
  {
   # stay clean
   @ob_end_clean();
   @set_time_limit(0);

   # keep binary data safe
   set_magic_quotes_runtime(0);

   $fh = fopen($file, 'rb') or die ('<b>ERROR:</b> php could not open (' . $fileName . ')');
   # content headers
   header("Content-Type: video/x-flv"); 

   # output file
   while(!feof($fh)) 
   {
     # output file without bandwidth limiting
     print(fread($fh, filesize($file))); 
   } 
  } 
 }

那么我该如何限制响应速度(限制为例如50 kb / s)

5 个答案:

答案 0 :(得分:4)

将文件输出更改为交错,而不是一次性输出整个文件。

# output file
while(!feof($fh)) 
{
    # output file without bandwidth limiting
    print(fread($fh, 51200)); # 51200 bytes = 50 kB
    sleep(1);
}

这将输出50kB然后等待一秒,直到输出整个文件。它应该将带宽限制在大约50kB /秒。

尽管这在PHP中是可行的,但我使用您的网络服务器来控制限制

答案 1 :(得分:2)

我不会用php来限制带宽:

对于Apache:Bandwidth Mod v0.7How-To - Bandwidth Limiter For Apache2

对于Nginx:http://wiki.nginx.org/NginxHttpCoreModule#limit_rate

对于Lighttpd:http://redmine.lighttpd.net/projects/lighttpd/wiki/Docs:TrafficShaping这甚至允许您在PHP中配置每个连接的速度

答案 2 :(得分:0)

您可以读取n个字节,然后按照建议here使用use sleep(1)等待一秒钟。

答案 3 :(得分:0)

我认为'Ben S'和'igorw'的方法是错误的,因为它们意味着无限的带宽,这是一个错误的假设。基本上是一个说

的脚本
while(!feof($fh)) {
   print(fread($fh, $chunk_size));
   sleep(1);
}
输出$ chunk_size字节数后,

将暂停一秒,无论花费多长时间。例如,如果您当前的吞吐量为100kb并且您希望以250kb进行流式传输,则上述脚本将花费2.5秒来执行print(),然后等待另一秒,从而有效地将实际带宽降低到大约70kb。

解决方案应该测量PHP完成print()statemnt所花费的时间,或者使用缓冲区并使用每个fread()调用flush。第一种方法是:

list($usec, $sec) = explode(' ', microtime());
$time_start = ((float)$usec + (float)$sec);
# output packet
print(fread($fh, $packet_size));
# get end time
list($usec, $sec) = explode(' ', microtime());
$time_stop = ((float)$usec + (float)$sec);
# wait if output is slower than $packet_interval
$time_difference = $time_stop - $time_start;
if($time_difference < (float)$packet_interval) {
    usleep((float)$packet_interval*1000000-(float)$time_difference*1000000);
}

而第二个类似于:

ob_start();
while(!feof($fh)) {
       print(fread($fh, $chunk_size));
       flush();
       ob_flush();
       sleep(1);
    }

答案 4 :(得分:0)

您可以将bandwidth-throttle/bandwidth-throttle附加到信息流:

use bandwidthThrottle\BandwidthThrottle;

$in  = fopen(__DIR__ . "/resources/video.mpg", "r");
$out = fopen("php://output", "w");

$throttle = new BandwidthThrottle();
$throttle->setRate(500, BandwidthThrottle::KIBIBYTES); // Set limit to 500KiB/s
$throttle->throttle($out);

stream_copy_to_stream($in, $out);