За последние 24 часа нас посетили 53738 программистов и 1772 робота. Сейчас ищут 823 программиста ...

fsockopen и ограничение скорости

Тема в разделе "Прочие вопросы по PHP", создана пользователем TrustNo1, 28 мар 2010.

  1. TrustNo1

    TrustNo1 Активный пользователь

    С нами с:
    28 мар 2010
    Сообщения:
    10
    Симпатии:
    0
    Доброго времени суток!
    Интересует вопрос ограничения скорости отдачи файла скриптом, получаемого через fsockopen до 50 кб/с
    Вот собственно код:
    PHP:
    1.  
    2. <?php
    3. $sock = @fsockopen($server, 80, $errno, $errstr, 30);
    4. if(!$sock)
    5. {
    6.   die('Cannot create socket! Error was: ' . $errstr);
    7. }
    8. $request = "GET /path/to/file HTTP/1.1\r\n";
    9. $request .= "Host: $server\r\n";
    10. $request .= "Accept: */*\r\n";
    11. $request .= "Connection: close\r\n";
    12. $request .= "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n";
    13. $request .= "Cookie: " . file_get_contents($cookies) . "\r\n";
    14. if($_SERVER['HTTP_RANGE'])
    15. {
    16.   $request .= "Range: {$_SERVER['HTTP_RANGE']}\r\n";  
    17. }
    18. $request .= "\r\n";
    19. fwrite($sock, $request);
    20. $line = fgets($sock);
    21. while($line != "\r\n")
    22. {
    23.   $line = fgets($sock);  
    24. }
    25. $_SERVER['HTTP_RANGE'] ? header('HTTP/1.1 206 Partial Content', true, 206) : header('HTTP/1.1 200 OK', true, 200);
    26. header("Content-Disposition: attachment");
    27. header('Content-type: audio/mpeg');
    28. header('Content-Length: '.$content_len);
    29. header('Accept-Ranges: bytes');
    30. header('Connection: close');
    31. $time_discret = 1;
    32. $download_speed = 51200;
    33. while(!feof($sock))
    34. {
    35.         $time_start = microtime(true);
    36.         echo fread($sock, ceil($download_speed*$time_discret));
    37.         flush();
    38.         $time_end = microtime(true);
    39.         $time = $time_end - $time_start;
    40.         if($time_discret-$time > 0) usleep(($time_discret-$time)*1000000);
    41. }
    42. fclose($sock);
    43. ?>
    44.  
    проблема заключается в том, что скрипт первые пару секунд отдает файл на скорости около 40 кб/с а потом практически ничего не отдает (или отдает на нереально мизерной скорости). Проснифферив запросы вычислил что скрипт всегда скачивает максимум 234.86 кб файла и дальше ни в какую не идет. Подскажите, в чем может быть проблема?
     
  2. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    не возьму в толк, что делает 39 строка?
     
  3. TrustNo1

    TrustNo1 Активный пользователь

    С нами с:
    28 мар 2010
    Сообщения:
    10
    Симпатии:
    0
    igordata
    по идее она выжидает определенное время перед тем как отправить следующий кусок данных - в данном случае секунду
    пример скрипта брал отсюда http://shaman.asiadata.ru/node/311
     
  4. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    ну и ужас. некоторые переменные неопределыны.
    попробуй удалить это
    зы. автор не знает о do...while а зря
     
  5. TrustNo1

    TrustNo1 Активный пользователь

    С нами с:
    28 мар 2010
    Сообщения:
    10
    Симпатии:
    0
    Mr.M.I.T.
    мне же ненадо отдавать заголовки полученные с сервера в теле файла, а нужно только данные.
    если убрать этот кусок нужно будет каким-то образом перематывать указатель в начало данных в сокете
     
  6. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    глянул на страничку. там есть рекомендации уменьшить время до 0,1 и включить эррор репорты в поток.
     
  7. TrustNo1

    TrustNo1 Активный пользователь

    С нами с:
    28 мар 2010
    Сообщения:
    10
    Симпатии:
    0
    изменил $discret_time на 0.1 - отдавать стало на нужной скорости но коннект в fsockopen рвется после получения 1.41-1.43 мб файла. в чем может быть проблема?

    UPD: включил все ошибки и разобрался - "Maximum execution time of 30 seconds exceeded"
     
  8. alBoo

    alBoo Активный пользователь

    С нами с:
    27 мар 2008
    Сообщения:
    63
    Симпатии:
    0
  9. lexa

    lexa Активный пользователь

    С нами с:
    22 июл 2007
    Сообщения:
    1.746
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    PHP:
    1. <?
    2. while (!feof($sock)){
    3.     echo fread($sock, $download_speed);
    4.     ob_flush();
    5.     flush();
    6.     sleep(1); // в секундах, да
    7. }
     
  10. TrustNo1

    TrustNo1 Активный пользователь

    С нами с:
    28 мар 2010
    Сообщения:
    10
    Симпатии:
    0
    alBoo
    я конечно понимаю что юзать модули сервака для такой задачи более верно, НО когда используется хостинг и доступа к конфе сервака разумеется нет, то приходится изобретать велосипед из подручных доступных средств
    lexa
    к сожалению в секундах нельзя..нужный эффект не достигается((

    по сабжу - проблему решил
    если кого интересует код то вот:
    PHP:
    1.  
    2. <?php
    3. $sock = @fsockopen($server, 80, $errno, $errstr, 30);
    4. if(!$sock)
    5. {
    6.   die('Cannot create socket! Error was: ' . $errstr);
    7. }
    8. $request = "GET /path/to/file HTTP/1.1\r\n";
    9. $request .= "Host: $server\r\n";
    10. $request .= "Accept: */*\r\n";
    11. $request .= "Connection: close\r\n";
    12. $request .= "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7\r\n";
    13. $request .= "Cookie: " . file_get_contents($cookies) . "\r\n";
    14. if($_SERVER['HTTP_RANGE'])
    15. {
    16.   $request .= "Range: {$_SERVER['HTTP_RANGE']}\r\n";  
    17. }
    18. $request .= "\r\n";
    19. fwrite($sock, $request);
    20. $line = fgets($sock);
    21. while($line != "\r\n")
    22. {
    23.   $line = fgets($sock);  
    24. }
    25. $_SERVER['HTTP_RANGE'] ? header('HTTP/1.1 206 Partial Content', true, 206) : header('HTTP/1.1 200 OK', true, 200);
    26. header("Content-Disposition: attachment");
    27. header('Content-type: audio/mpeg');
    28. header('Content-Length: '.$content_len);
    29. header('Accept-Ranges: bytes');
    30. header('Connection: close');
    31. $time_discret = 0.1;
    32. $download_speed = 51200;
    33. while(!feof($sock))
    34. {
    35.         $time_start = microtime(true);
    36.         echo fread($sock, ceil($download_speed*$time_discret));
    37.         flush();
    38.         $time_end = microtime(true);
    39.         $time = $time_end - $time_start;
    40.         if($time_discret-$time > 0) usleep(($time_discret-$time)*1000000);
    41. }
    42. fclose($sock);
    43. ?>
    44.  
     
  11. dj--alex

    dj--alex Активный пользователь

    С нами с:
    29 ноя 2007
    Сообщения:
    184
    Симпатии:
    0
    вот если бы ещё память ограничить
    у мея свой модуль для отдачи

    но память readfile забивает если файл на гиг - он его целиком в оперу загружает...
    вот это бы исправить
     
  12. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    мм. ну читайте по 8 килобайт...
     
  13. dj--alex

    dj--alex Активный пользователь

    С нами с:
    29 ноя 2007
    Сообщения:
    184
    Симпатии:
    0
    а что на ПХП разве реально отдавать файлы больше 1 гига не загружая их целиком в память?
     
  14. Psih

    Psih Активный пользователь
    Команда форума Модератор

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    dj--alex
    PHP:
    1. <?php
    2.  
    3. $f = fopen('/path/to/file', 'r') or die('Can\'t find the file!');
    4. while (!feof($f)) {
    5.     echo fread($f, 128 * 1024); // Read and give out 128KB chunk  
    6. }
    7. fclose($f);
    8.  
    Очевидно, нет? :)
    Output buffering естественно должен быть отключен.
     
  15. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    fread() reads up to length bytes from the file pointer referenced by handle. Reading stops as soon as one of the following conditions is met:
    - length bytes have been read
    - EOF (end of file) is reached
    - a packet becomes available (for network streams)
    - 8192 bytes have been read (after opening userspace stream)


    А этот юзеспейс стрим это что?
     
  16. dj--alex

    dj--alex Активный пользователь

    С нами с:
    29 ноя 2007
    Сообщения:
    184
    Симпатии:
    0
    не помогает

    $f = fopen($file, 'r') or die('Can\'t find the file!');
    while (!feof($f)) {
    echo fread($f, 16 * 1024); // Read and give out 16KB chunk
    ob_flush ();
    }
    fclose($f);

    даже так не работает , мгновенно исчезают 2 гб оперативы
    3 скачки - 6гб оперативы . более скачек - комп дико лагать и тормозить начинает
    причем он их ещё и кэширует в памяти
    т.е. если в первый раз скорость была 30мб\с то в следующие разы она почти в 3 раза выше - уже 80мб\с
    ....

    попробовал класс отсюда...
    http://www.php.ru/forum/viewtopic.php?t ... 787be8d09b

    использовал так...
    $object = New download ($file,$name=$filename, $resume=1, $max_speed=0);
    // echo $object->name;
    $object->download_file ();

    память вроде перестала пропадать..то что надо!!!
    проблема решена, спасибо!!!