Параллельное выполнение запросов через сокеты?

Discussion in 'PHP' started by Darkweider, 19 Sep 2007.

  1. Darkweider

    Darkweider Elder - Старейшина

    Joined:
    8 Feb 2007
    Messages:
    142
    Likes Received:
    13
    Reputations:
    0
    Вообщем столкнулся с такой проблемой, хочу быстрый парсер страниц написать. Как парсить страницы понял и разобрался... Проблема в том что через file_get_contents() все тормозно получается, слышал что можно параллельно информацию получать через сокеты, т.е. выполнять сразу несколько запросов в нескольким сайтам... Даже пример нашел, но не могу понять как переделать его=\ под парсер... Пожалуйста помогите разобраться уже который день думаю как переделать... Как работают незаблокориванные соксы не могу понять че-то... Пример, очень распространенный...
    PHP:
    <?
    // путь, где расположены скрипты
    $path "http://domain.com/path/";

    // число потоков
    $max_threads 20;


    // инициализация

    $sockets = array();
    $done false;

    // будем работать, к примеру с набором
    // ключевых слов

    $keywords fopen("keywords.txt"'r');

    // приступаем к многопоточной работе

    while (!$done)
    {
    // если обнаружен файл,
    // то прекращаем выполнение скрипта

    if (file_exists('stop-file'))
    die;

    // если число запущенных потоков меньше
    // разрешенного максимума
    // то запускаем потоки еще

    if ($max_threads count($sockets))
    {

    if (!
    feof($keywords))
    {
    $buffer = array();

    // читаем ключевое слово
    // в реальности в этот массив можно
    // положить очень много всего
    // а не только одно ключевое слово…

    $buffer[] = trim(fgets($keywords));

    // задаем данные для запуска сокета
    // request.php - это тот файл,
    // которые делает “дело”

    $query_url $path 'request.php';
    $url_info parse_url($query_url);

    $url_info[port] = ($url_info[port]) ? $url_info[port] : 80;
    $url_info[path] = ($url_info[path]) ? $url_info[path] : /;
    $url_info[query] = ($url_info[query]) ? ?” $url_info[query] : “”;

    // пакуем данные для передачи
    // в генерирующий скрипт
    // использование serialize очень удобно,
    // так как позволяет
    // залить в request.php мегабайты данных

    $request serialize($buffer);

    // формируем запрос для передачи по сокету

    $query “POST ” $url_info[path] . ” HTTP/1.1\r\n”;
    $query $query “Content-Typetext/xml\r\n”;
    $query $query “Host” $url_info[host] . \r\n”;
    $query $query “Content-length” . (strlen($request)) . \r\n\r\n”;
    $query $query $request;

    // создаем сокет, переводим его
    // в неблокирующий режим и запускаем
    // обработчик запросов

    $errno 0;
    $error “”;

    $socket fsockopen($url_info[host], $url_info[port], $errno$error30);
    stream_set_blocking($socket0);
    stream_set_timeout($socket3600);
    fputs($socket$query);

    // запоминаем запущенный сокет

    $sockets[md5(time())] = $socket;
    }
    }

    // читаем данные из сокета. формально они нам
    // не нужны, но это позволяет
    // отработать обработчкику запросов

    reset($sockets);
    while (
    $socket current($sockets))
    {
    if (
    feof($socket))
    {
    // убиваем сокет, который отработал

    unset($sockets[key($sockets)]);
    }
    else
    {
    // читаем данные из сокета

    $temp fgets($socket1000);
    }

    // обрабатываем следующий сокет

    next($sockets);
    }

    // делаем небольщую задержку,
    // иначе загруженность сервера
    // приближается к 100 процентам

    sleep(1);

    // если нет активных сокетов, то можно выходить

    if (count($sockets) == 0)
    $done true;
    }

    fclose($keywords);

    die;
    ?>
     
  2. ant0ha

    ant0ha Elder - Старейшина

    Joined:
    22 May 2007
    Messages:
    130
    Likes Received:
    50
    Reputations:
    13
  3. Darkweider

    Darkweider Elder - Старейшина

    Joined:
    8 Feb 2007
    Messages:
    142
    Likes Received:
    13
    Reputations:
    0
    Вот еще нашел пример помогите кто-нибудь подробно разобраться неплохая может статья выйдет.... мало где нашел подробное описание.... Я конешно понимаю надо смотреть каменты и т.п. ,но все таки когда теретически понимаешь как это организуется, только тогда появлятся возможность написать что-то свое...
    PHP:
    < ?php
    $hosts 
    = array("host1.sample.com""host2.sample.com");
    $timeout 15;
    $status = array();
    $sockets = array();
    /* Инициируем соединения ко всем хостам одновременно */
    foreach ($hosts as $id => $host) {
        
    $s stream_socket_client("$host:80"$errno$errstr$timeout
            
    STREAM_CLIENT_ASYNC_CONNECT|STREAM_CLIENT_CONNECT);
        if (
    $s) {
            
    $sockets[$id] = $s;
            
    $status[$id] = "in progress";
        } else {
            
    $status[$id] = "failed, $errno $errstr";
        }
    }
    /* Теперь ожидаем результат */
    while (count($sockets)) {
        
    $read $write $sockets;
        
    /* Вот она - магическая функция - пояснения ниже */
        
    $n stream_select($read$write$e null$timeout);
        if (
    $n 0) {
            
    /* доступные для чтения сокеты готовы отдать нам данные 
               или попытка провалилась 
            */
            
    foreach ($read as $r) {
                
    $id array_search($r$sockets);
                
    $data fread($r8192);
                if (
    strlen($data) == 0) {
                    if (
    $status[$id] == "in progress") {
                        
    $status[$id] = "failed to connect";
                    }
                    
    fclose($r);
                    unset(
    $sockets[$id]);
                } else {
                    
    $status[$id] .= $data;
                }
            }
            
    /* доступные для записи сокеты могут принимать 
                HTTP-запросы 
            */
            
    foreach ($write as $w) {
                
    $id array_search($w$sockets);
                
    fwrite($w"HEAD / HTTP/1.0rnHost: "
                    
    $hosts[$id] .  "rnrn");
                
    $status[$id] = "waiting for response";
            }
        } else {
            
    /* ожидаем таймаут; подразумевается, что все сокеты, 
                ассоциированные с массивом $sockets не сработали 
            */
            
    foreach ($sockets as $id => $s) {
                
    $status[$id] = "timed out " $status[$id];
            }
            break;
        }
    }
    foreach (
    $hosts as $id => $host) {
        echo 
    "Host: $hostn";
        echo 
    "Status: " $status[$id] . "nn";
    }
    ?> 
    Помогите расписать по блокам...Вписываю какие-нибудь сайты,запускаю и все виснет...
     
    #3 Darkweider, 19 Sep 2007
    Last edited: 19 Sep 2007