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