HTTP status checker

Тема в разделе "Как сделать...", создана пользователем terkin, 24 сен 2008.

Статус темы:
Закрыта.
  1. terkin

    terkin

    Регистр.:
    9 дек 2006
    Сообщения:
    513
    Симпатии:
    162
    Мультипоточный чекер ссылок на PHP и Curl, вроде как всё правильно сделано, но беспокоит одна вещ, часто где код ответа должен быть 200 мне возвращает 0 или 503, я так понимаю - это из-за того что скрипт шлёт слишком быстро запросы серверу. Но вот в руководстве по курлу я так и не смог найти как выставить задержку при многопоточных запросах, поэтому прошу помощи, кто сможет доделать

    PHP:
    <?php
     
    // $ma - массив с нашими урлами с http://
      
    $mh curl_multi_init();
      
    $handles = array();

      for(
    $i=0;$i<count($ma);$i++)
      {
        
    $ch curl_init();
        
    curl_setopt($chCURLOPT_URL$ma[$i]);
        
    curl_setopt($chCURLOPT_HEADER0);
        
    curl_setopt($chCURLOPT_RETURNTRANSFERtrue);
        
    curl_setopt($chCURLOPT_TIMEOUT30);
        
    curl_multi_add_handle($mh,$ch);
        
    $handles[] = $ch;
      }
      
    $running=null;
      do
      {
        
    curl_multi_exec($mh,$running);
      } while (
    $running 0);

      for(
    $i=0;$i<count($handles);$i++)
      {
        
    $output.=$ma[$i].' '.curl_getinfo($handles[$i], CURLINFO_HTTP_CODE).'<br />';
        
    curl_multi_remove_handle($mh,$handles[$i]);
      }
      echo 
    $output;
      
    curl_multi_close($mh);


    ?>
     
  2. elcaste

    elcaste

    Регистр.:
    30 ноя 2007
    Сообщения:
    322
    Симпатии:
    175
    В твоем случае использование именно CURL критично? Можно ведь решить проблему н****кирующими сокетами.
     
  3. terkin

    terkin

    Регистр.:
    9 дек 2006
    Сообщения:
    513
    Симпатии:
    162
    В моём случае любой способ хорош лижбы работал, ну и в несколько потоков, так как линков чекать нужно много
     
  4. gregzem

    gregzem

    Регистр.:
    21 окт 2007
    Сообщения:
    202
    Симпатии:
    66
    1. н****кирующие сокеты на порядок усложнят задачу. По большому счету придется с нуля тот самый cURL и написать.

    2. в сURL нет настроек для задания периода (интервала) отправки запросов при режиме multi-thread

    3. Для запроса HEAD оптимальнее использовать самодельный веб-клиент на обычных блокирующих сокетах (fsockopen,...)

    4. Распараллелить задачу можно не только через потоки, но и через процессы. А именно: один скрипт берет на вход список урлов, делит их на N порций, раскладывает по файлам или в таблицу с N идентификаторами и запускает N процессов, каждый из которых является однопотоковым веб-клиентом-чекером и проверяет свою порцию урлов. Результаты аналогично складываются в N файлов или в ту же базу, а затем объединяются.

    UPD: прошу прощения за вопрос, но почему именно php? :)
     
  5. elcaste

    elcaste

    Регистр.:
    30 ноя 2007
    Сообщения:
    322
    Симпатии:
    175
    По поводу сокетов:
    PHP:
    <?php
    function multi_get ($urlArr$timeout 5$sleep 0) {
        
    $sockets = Array();
        
    $urlInfo = Array();
        
    $retDone = Array();
        
    $retData = Array();
        
    $errno = Array();
        
    $errstr = Array();
        for (
    $x=0;$x<count($urlArr);$x++) {
            
    $urlInfo[$x] = parse_url($urlArr[$x]);
            
    $getstr = ($urlInfo[$x][path] ? $urlInfo[$x][path] : '/').($urlInfo[$x][query] ? '?'.$urlInfo[$x][query] : '');
            do {
                
    $sockets[$x] = fsockopen($urlInfo[$x][host], 80$errno[$x], $errstr[$x], $timeout);
            } while (!
    $sockets[$x]);
            
    socket_set_blocking($sockets[$x],FALSE);
            
    $HEAD "HEAD ".$urlInfo[$x][path]."$getstr HTTP/1.0\r\n";
            
    $HEAD.= "Host: ".$urlInfo[$x][host]."\r\n";
            
    $HEAD.= "\r\n";
            
    fputs($sockets[$x], $HEAD);
            
    sleep($sleep);
        }
        while (!
    $done) {
            for (
    $x=0$x count($urlArr);$x++) {
                if (!
    feof($sockets[$x])) {
                    if (
    $retData[$x]) {
                        
    $retData[$x] .= fread($sockets[$x], 8192);
                    } else {
                        
    $retData[$x] = fread($sockets[$x], 8192);
                    }
                } else {
                    
    $retDone[$x] = 1;
                }
            }
            
    $done = (array_sum($retDone) == count($urlArr));
        }
        return 
    $retData;
    }

    // $url массив с урлами

    $retData multi_get($url);

    foreach (
    $retData as $key => $fe){
        
    preg_match("/[0-9]{3}/"substr($fe020), $pm);
        
    $output .= $url[$key].' '.$pm[0].'<br>';
    }
    echo 
    $output
    ?>
    Кстати, как заметил gregzem, запрос HEAD занимает доли секунды. Так что, если не нужен весь ответ сервера, то простой цикл с обычными сокетами и небольшим таймаутом вполне подойдет.
     
  6. skabbit

    skabbit Постоялец

    Регистр.:
    6 дек 2007
    Сообщения:
    88
    Симпатии:
    1
    друзья - perl + lwp::useragent = очень простая реализация порой сложных задач.
    там ещё mech есть, который умеет совсем под браузер косить, но это уже для задач типа сабмита.
    (сейчас меня как пнут за perl :nezn: )
     
Статус темы:
Закрыта.