【问题标题】:How to limit speed of outgoing response from php script?如何限制来自 php 脚本的传出响应速度?
【发布时间】:2010-06-24 14:11:32
【问题描述】:

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

(现在我有这样的代码)

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)

【问题讨论】:

    标签: php file response bandwidth limiting


    【解决方案1】:

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

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

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

    尽管这在 PHP 中是可能的,但我会使用您的网络服务器来控制节流

    【讨论】:

    • flush打印后的缓冲区将确保每秒稳定的写入流,但这不是绝对必要的。
    • 请添加正确的 cmets 并刷新,以便认为这个答案完全正确。
    【解决方案2】:

    我不会用php来限制带宽:

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

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

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        我认为“Ben S”和“igorw”的方法是错误的,因为它们暗示了无限带宽,这是一个错误的假设。基本上是一个脚本,说

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

        在输出 $chunk_size 个字节后会暂停一秒钟,无论它花费了多长时间。例如,如果您当前的吞吐量为 100kb,而您希望以 250kb 的速度进行流式传输,则上面的脚本将花费 2.5 秒来执行 print(),然后再等待一秒,从而有效地将实际带宽降低到 70kb 左右。

        解决方案应该测量 PHP 完成 print() 语句所用的时间,或者使用缓冲区并在每次 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);
            }
        

        【讨论】:

          【解决方案5】:

          您可以将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);
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-07-30
            • 1970-01-01
            • 1970-01-01
            • 2017-06-21
            • 2015-05-14
            • 2011-12-04
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多