2010-06-24 68 views
2

如何限制來自php腳本的傳出響應速度?所以我有一個腳本生成保持連接的數據。它只是打開文件並讀取它。如何限制傳出速度如何限制從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 /秒)的速度

回答

4

更改文件輸出是交錯的,而不是一次輸出整個文件。

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

這將輸出50KB然後等待1秒鐘,直至整個文件輸出。它應該將帶寬限制在50kB /秒左右。

儘管在PHP中這是可能的,但我會使用您的網絡服務器來控制節流

+1

'flush'ing後的緩衝打印將確保每秒都有穩定的寫入流,儘管並非嚴格必要。 – Chadwick 2010-06-24 14:25:13

+0

請添加正確的評論和沖洗,所以認爲這個答案完全正確。 – Rella 2010-06-25 09:12:00

0

您可以讀取n個字節,然後使用sleep(1)等待一秒,如建議here

0

我認爲'本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); 
    } 
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);