PHP Multi-threading - Форум успешных вебмастеров - GoFuckBiz.com - Страница 2
 
 
Форум успешных вебмастеров - GoFuckBiz.com

  Форум успешных вебмастеров - GoFuckBiz.com > Бизнес-решения > Скрипты, программы и технические решения
Дата
USD/RUB89.2589
BTC/USD68518.0581
Скрипты, программы и технические решения Обсуждаем скрипты, программы и новые технологии.

Закрытая тема
Опции темы Опции просмотра
Старый 30.06.2010, 17:46
Start Post: PHP Multi-threading 
  #11
Drunk Monk
Je suis moine ivre
 
Аватар для Drunk Monk
 
Регистрация: 03.03.2009
Сообщений: 15,243
Бабло: $797172957
По умолчанию

Кто как реализует многопоточность на пыхе?

Накидайте инфы по рабочим схемам, плиз
Drunk Monk вне форума  
Старый 01.07.2010, 12:28   #12
dveredel
Читатель
 
Аватар для dveredel
 
Регистрация: 23.11.2007
Сообщений: 420
Бабло: $48745
По умолчанию

Нашел у себя древний примерчик полностью неблокируемых сокетов, возможно я его тут уже и выкладывал - по поиску найти не смог.

Прямо сейчас "на рабочесть" не проверял

PHP код:
// Простейший пример полностью асинхронной загрузки нескольких хостов
// ВНИМАНИЕ: всяческие проверки, красивая логика и обработка ошибок выходят за рамки данного примера
// В нормальной реализации все делается по человечески на объектах и более гибко


// Массив ХОСТОВ  (а не урлов)
// это примитивный пример, который не хочется загромождать разбором урла и т.п.
$urls = array(
    
'cuca.ru',
    
'savvot.ru',
    
'livejournalz.com',
    
'google.com',
    
'ya.ru'
);

$sockconn = array();  // Сокеты в процессе коннекта
$socksel = array();   // "Законнекченные" сокеты для записи-чтения :)


//Инициализируем массив сокетов
foreach($urls as $u) {
    
// создаем сокет
    
$sock socket_create(AF_INETSOCK_STREAMSOL_TCP); 
    if(
$sock === false) die('нипалучаицца');

    
// отключаем блокировку (включаем асинхронность)
    
socket_set_nonblock($sock);

    
// заносим данные в массив
    
$sockconn[] = array(
        
'socket' => $sock
        
'host' => $u
        
'ip' => gethostbyname($u),
        
'msg' => "GET / HTTP/1.0\r\nHost: $u\r\n\r\n"  // А можно и HEAD, если на 200 проверять
    
);
}

//Погнали...
do {
    
// Неблокируемые сокеты в процессе коннекта обрабатываются по-хитрому.
    
foreach($sockconn as $key => $d) {
        
$sock $d['socket'];

        
// время начала коннекта для обработки таймаутов
        
if(!isset($d['time'])) $d['time'] = microtime(true); 
        
        
// Фишка в том что при вызове коннекта nonblocked сокета, выполнение скрипта продолжается дальше
        // без ожидания выполнения функции, и чтобы узнать на каком этапе соединения находится сокет
        // необходимо в цикле вызывать ту же функцию соединения до появления флага соединения,
        // при этом обработка таймаута ложится на плечи самого программиста.
        
$conn = @socket_connect($sock$ip80);
        
        
$error socket_last_error($sock);   // смотрим как там поживает наш сокет
        
        // Флаги  SOCKET_EINPROGRESS и SOCKET_EISCONN указывают что сокет еще коннектится
        // а флаг SOCKET_EALREADY говорит нам что все пучком
        // флаги, отличные от перечисленных следует считать за ошибку
        
if ($error != SOCKET_EINPROGRESS && $error != SOCKET_EALREADY && $error != SOCKET_EISCONN) {
            echo 
'<p>Эггог соединения: '.$d['url'].'</p>'
            
socket_close($sock); // не забываем освобождать открытые сокеты для системы
            
unset($sockconn[$key]);
            
        } elseif(
$conn) {                // Все пучком - законнектились
            
echo '<p>Соединились с: '.$d['url'].' :: '.(microtime(true) - $d['time']).'</p>';
            
$d['conn_time'] = microtime(true);
            
$socksel[$key] = $d;        // Регистрируем умницу-сокета в массиве для чтения-записи
            
unset($sockconn[$key]);     // и удаляем его из массива тех кто еще коннектится
            
        
} elseif((microtime(true) - $d['time']) > 2) {     // Таймаут 2 секунды.
            
echo '<p>Connect timeout on: '.$d['url'].'</p>';
            
socket_close($sock);     // не забываем освобождать открытые сокеты для системы
            
unset($sockconn[$key]);
        }
    }
    
    
// Обрабатываем сокеты которые уже готовы ко всякому.
    
$reads = array();
    foreach(
$socksel as $key => $d) {
        
$sock $d['socket'];
        
        
// Если мы еще не писАли в сокет, то...
        
if(!isset($d['w_time'])) {        
            
// Время начала записи в сокет
            
$d['w_time'] = microtime(true);
            
$num socket_write($sock$d['msg']);
            if(
$num === false) {
                echo 
'<p>Write error to: '.$d['url'].' :: '.(microtime(true)-$d['w_time']).'</p>';
                
$d['w_time'] = microtime(true);
                
socket_close($sock); 
                unset(
$socksel[$key]);
            } else {
                
//echo '<p>Write succes : '.$num.'</p>';    
                
$d['r_time'] = microtime(true);                
            }
        } else{
            if((
microtime(true)-$d['r_time']) > 20) {
                echo 
'<p>Read timeout: '.$d['url'];
                
socket_close($sock); 
                unset(
$socksel[$sock]);            
            } else {
                
$reads[] = $sock;
            }
        }
    }
    

    
// Читаем из сокетов которые "хотят нам что то сказать"
    
if($reads) {
        
$writes $exs NULL;
        if(
socket_select($reads$writes$exs0) === false) die('Select error: '.socket_last_error());
        foreach(
$reads as $sock) {
            
$d = &$socksel[$sock];

            
// время начала чтения из сокета
            
if(!isset($d['r_time'])) $d['r_time'] = microtime(true);

            
// читаем....   (количество байт для чтения взято "с потолка")
            
$rd socket_read($sock17000); 
            
            
// сравнение обязательно проводить точное с учетом типа ===
            // если false - то несудьба
            
if($rd === false) {
                echo 
'<p>Error reading: '.$d['url'].'</p>';
                
socket_close($sock); 
                unset(
$socksel[$sock]);
            
// если пустая строка - чтение завершено
            
} elseif($rd === '') {
                echo 
'<p>Data received: '.$d['url'].'<br>'.strlen($d['cnt']).'   ::: '.(microtime(true)-$d['time']).'</p>';
                list(
$header) = explode("\r\n\r\n"$d['cnt']);
                
//echo '<pre>'.htmlspecialchars($header).'</pre>';
                
socket_close($sock); 
                unset(
$socksel[$sock]);
            
// получили очередную порцию данных
            
} else {
                @
$d['cnt'] .= $rd;
            }
        }
    }
} while(
count($sockconn)>|| count($socksel)>0); 
dveredel вне форума  
Старый 01.07.2010, 19:15   #13
rushter
Senior Member
 
Регистрация: 28.11.2009
Сообщений: 1,787
Бабло: $299365
По умолчанию

Используйте нормальные языки и не будет никаких проблем. От этих велосипедных многопоточностей толку мало.
rushter вне форума  
Старый 01.07.2010, 19:40   #14
qazxcvbnm
Ниибаца крутой програмер
 
Аватар для qazxcvbnm
 
Регистрация: 04.08.2009
Сообщений: 904
Бабло: $177555
По умолчанию

кто знает как в мультикурле обратится не к веб cтраницам, а к локальному скрипту, при условии что скрипт выполняются напрямую через интепритатор php без использования сервера (>php.exe script.php par1 par2)

обращение к bat файлу котрый в свою очередь вызывает скрипт ничего не возвращает

заголовки такие

PHP код:
            [url] => http://C:\xampp\htdocs\scripts\temporary\1.bat
            
[content_type] => 
            [
http_code] => 0
            
[header_size] => 0
            
[request_size] => 0
            
[filetime] => -1
            
[ssl_verify_result] => 0
            
[redirect_count] => 0
            
[total_time] => 0
            
[namelookup_time] => 0
            
[connect_time] => 0
            
[pretransfer_time] => 0
            
[size_upload] => 0
            
[size_download] => 0
            
[speed_download] => 0
            
[speed_upload] => 0
            
[download_content_length] => -1
            
[upload_content_length] => -1
            
[starttransfer_time] => 0
            
[redirect_time] => 
на каком бля этапе к локальному адресу присоединяется http:// ?
qazxcvbnm вне форума  
Старый 01.07.2010, 20:02   #15
chesser
автоматизирую интернеты
 
Аватар для chesser
 
Регистрация: 05.07.2009
Адрес: chesser.ru
Сообщений: 3,348
Бабло: $470735
По умолчанию

qazxcvbnm
никак,
curl используется для коннекта(мультипоточного если надо) к серверу по определенным протоколам. Использование его мультипоточности позволяет сократить время ожидание коннекта к серверу, что очень много времени отнимает, если коннектиться в один поток.

Тебе же нужна мультизадачность/мультипроцессность.
смотри в сторону fork: http://www.php.net/manual/en/book.pcntl.php - только сразу готовь побольше памяти
или http://gearman.org интересный вариант, правда я его сам не смотрел
__________________
USA и NL серверы и VPS | wiki | блог | Drupal | NginxТДС
Ave, Google, morituri te salutant! © chesser
chesser вне форума  
Старый 01.07.2010, 20:14   #16
sergeospb
коплю на феррари
 
Регистрация: 03.07.2008
Сообщений: 1,246
Бабло: $148195
По умолчанию

Цитата:
Сообщение от chesser Посмотреть сообщение
qazxcvbnm
никак,
curl используется для коннекта(мультипоточного если надо) к серверу по определенным протоколам. Использование его мультипоточности позволяет сократить время ожидание коннекта к серверу, что очень много времени отнимает, если коннектиться в один поток.

Тебе же нужна мультизадачность/мультипроцессность.
смотри в сторону fork: http://www.php.net/manual/en/book.pcntl.php - только сразу готовь побольше памяти
или http://gearman.org интересный вариант, правда я его сам не смотрел
венда и форки вещи несовместимые, только posix
sergeospb вне форума  
Старый 01.07.2010, 20:25   #17
chesser
автоматизирую интернеты
 
Аватар для chesser
 
Регистрация: 05.07.2009
Адрес: chesser.ru
Сообщений: 3,348
Бабло: $470735
По умолчанию

Цитата:
Сообщение от sergeospb Посмотреть сообщение
венда и форки вещи несовместимые, только posix
а, может, что-то про винду и не подумал
на nix системах сравнивал форки и курл-мультипоточность, разница очень большая. Форк выжырает всю память на сервере, а коннектов все равно мало. Курл же наоборот, копейки памяти позволили обслуживать очень много коннектов. Точные цифры не помню.
__________________
USA и NL серверы и VPS | wiki | блог | Drupal | NginxТДС
Ave, Google, morituri te salutant! © chesser
chesser вне форума  
Старый 01.07.2010, 20:36   #18
qazxcvbnm
Ниибаца крутой програмер
 
Аватар для qazxcvbnm
 
Регистрация: 04.08.2009
Сообщений: 904
Бабло: $177555
По умолчанию

Цитата:
Сообщение от chesser Посмотреть сообщение
qazxcvbnm
никак,
curl используется для коннекта(мультипоточного если надо) к серверу по определенным протоколам. Использование его мультипоточности позволяет сократить время ожидание коннекта к серверу, что очень много времени отнимает, если коннектиться в один поток.
да уже понял ... вспомнил что курл ниибацо хорош для разных протоколов, а при обращении к локальным файлам никаких же протоколов не используется

хотя, если запустить сервер и обратиться к локальному адресу 127.0.0.1/script.php то таки работает

в пустых циклах от 0 до 10.000 по очереди скрипт (10 запросов) выполнялся почти минуту (core2duo e45)
а при 10 потоках за несколько секунд

так что работает ... просто я хотел без запуска сервера
qazxcvbnm вне форума  
Старый 01.07.2010, 22:34   #19
Домкрат
Дохуя дорвейщик
 
Аватар для Домкрат
 
Регистрация: 26.11.2008
Сообщений: 898
Бабло: $55079
По умолчанию

Цитата:
Сообщение от rushter Посмотреть сообщение
Используйте нормальные языки и не будет никаких проблем. От этих велосипедных многопоточностей толку мало.
вебмастерам нахуй не нужна многопоточность (читай, форки). тут имеется в виду параллельная обработка множества коннектов, каковая сейчас прекрасно реализуется на сокетах, ничем не хуже других языков.
__________________
If you can dream - and not make dreams your master
Домкрат вне форума  
Старый 02.07.2010, 20:16   #20
qazxcvbnm
Ниибаца крутой програмер
 
Аватар для qazxcvbnm
 
Регистрация: 04.08.2009
Сообщений: 904
Бабло: $177555
По умолчанию

чтобы без запуска сервера можно exec'ом открывать экземпляры стороннего скрипта с определёнными параметрами и чтобы результаты этой промежуточной паралельной обработки записывались во временные файлы, а в основном скрипте, после exec'ов отслеживать появление этих файлов и считывать из них данные и обрабатывать информацию дальше
qazxcvbnm вне форума  
Старый 02.07.2010, 23:06   #21
chesser
автоматизирую интернеты
 
Аватар для chesser
 
Регистрация: 05.07.2009
Адрес: chesser.ru
Сообщений: 3,348
Бабло: $470735
По умолчанию

Цитата:
Сообщение от qazxcvbnm Посмотреть сообщение
чтобы без запуска сервера можно exec'ом открывать экземпляры стороннего скрипта с определёнными параметрами и чтобы результаты этой промежуточной паралельной обработки записывались во временные файлы, а в основном скрипте, после exec'ов отслеживать появление этих файлов и считывать из них данные и обрабатывать информацию дальше
exec - это обычный exec() ? - не будет работать параллельно, т.к. главный скрипт будет ждать пока отработает каждый из запущенных exec'ов.
То, о чем ты говоришь, это и есть форк(ну или что-то такое) - когда главный процесс запускает подпроцессы, которые почти являются отдельными скриптами.
__________________
USA и NL серверы и VPS | wiki | блог | Drupal | NginxТДС
Ave, Google, morituri te salutant! © chesser
chesser вне форума  
Закрытая тема