Как ограничить скорость исходящего ответа от 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 кбит / с)
Измените вывод файла, чтобы он был помещен в шахматном порядке, чтобы выводить весь файл за один раз.
# output file while(!feof($fh)) { # output file without bandwidth limiting print(fread($fh, 51200)); # 51200 bytes = 50 kB sleep(1); }
в# output file while(!feof($fh)) { # output file without bandwidth limiting print(fread($fh, 51200)); # 51200 bytes = 50 kB sleep(1); }
Это приведет к выходу 50kB, а затем подождите одну секунду, пока не будет выведен весь файл. Он должен ограничивать пропускную способность до 50 кБ / с.
Несмотря на то, что это возможно в PHP, я бы использовал ваш веб-сервер для управления дросселированием .
Я бы не использовал php для ограничения пропускной способности:
Для Apache: Bandwidth Mod v0.7 ( How-To – Ограничитель пропускной способности для Apache2 )
Для Nginx: http://wiki.nginx.org/NginxHttpCoreModule#limit_rate
Для Lighttpd: http://redmine.lighttpd.net/projects/lighttpd/wiki/Docs:TrafficShaping Это даже позволяет вам настроить скорость для каждого соединения в PHP
Вы можете прочитать n байтов, а затем использовать sleep (1), чтобы подождать секунду, как это предлагается здесь .
Я думаю, что метод «Бен С» и «igorw» неверен, потому что они подразумевают неограниченную пропускную способность, которая является ложным предположением. В основном сценарий, который говорит
while(!feof($fh)) { print(fread($fh, $chunk_size)); sleep(1); }
будет приостановлен на секунду после вывода $ chunk_size числа байтов, независимо от того, сколько времени прошло. Если, например, если ваша текущая пропускная способность составляет 100 кбайт, а вы хотите передать ее на скорости 250 кбайт, для выполнения печати () будет выполняться 2,5 секунды для выполнения печати (), а затем ждать еще одну секунду, эффективно нажимая реальную полосу пропускания примерно до 70 кб.
Решение должно либо измерить время, необходимое PHP для завершения print () statemnt, либо использовать буфер и сбросить флажок с каждым fread (). Первый подход:
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); }
Вы могли бы подключить 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);