|
| Дата |
|
USD/RUB | 89.2589 | BTC/USD | 68518.0581 |
|
|
|
Скрипты, программы и технические решения Обсуждаем скрипты, программы и новые технологии. |
30.06.2010, 17:46
|
Start Post: PHP Multi-threading
|
Je suis moine ivre
Регистрация: 03.03.2009
Сообщений: 15,243
Бабло: $797172957
|
Кто как реализует многопоточность на пыхе?
Накидайте инфы по рабочим схемам, плиз
|
|
|
01.07.2010, 12:28
|
#12
|
Читатель
Регистрация: 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_INET, SOCK_STREAM, SOL_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, $ip, 80);
$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, $exs, 0) === 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($sock, 17000);
// сравнение обязательно проводить точное с учетом типа ===
// если 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)>0 || count($socksel)>0);
|
|
|
01.07.2010, 19:15
|
#13
|
Senior Member
Регистрация: 28.11.2009
Сообщений: 1,787
Бабло: $299365
|
Используйте нормальные языки и не будет никаких проблем. От этих велосипедных многопоточностей толку мало.
|
|
|
01.07.2010, 19:40
|
#14
|
Ниибаца крутой програмер
Регистрация: 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] => 0
на каком бля этапе к локальному адресу присоединяется http:// ?
|
|
|
01.07.2010, 20:02
|
#15
|
автоматизирую интернеты
Регистрация: 05.07.2009
Адрес: chesser.ru
Сообщений: 3,348
Бабло: $470735
|
qazxcvbnm
никак,
curl используется для коннекта(мультипоточного если надо) к серверу по определенным протоколам. Использование его мультипоточности позволяет сократить время ожидание коннекта к серверу, что очень много времени отнимает, если коннектиться в один поток.
Тебе же нужна мультизадачность/мультипроцессность.
смотри в сторону fork: http://www.php.net/manual/en/book.pcntl.php - только сразу готовь побольше памяти
или http://gearman.org интересный вариант, правда я его сам не смотрел
|
|
|
01.07.2010, 20:14
|
#16
|
коплю на феррари
Регистрация: 03.07.2008
Сообщений: 1,246
Бабло: $148195
|
Цитата:
Сообщение от chesser
qazxcvbnm
никак,
curl используется для коннекта(мультипоточного если надо) к серверу по определенным протоколам. Использование его мультипоточности позволяет сократить время ожидание коннекта к серверу, что очень много времени отнимает, если коннектиться в один поток.
Тебе же нужна мультизадачность/мультипроцессность.
смотри в сторону fork: http://www.php.net/manual/en/book.pcntl.php - только сразу готовь побольше памяти
или http://gearman.org интересный вариант, правда я его сам не смотрел
|
венда и форки вещи несовместимые, только posix
|
|
|
01.07.2010, 20:25
|
#17
|
автоматизирую интернеты
Регистрация: 05.07.2009
Адрес: chesser.ru
Сообщений: 3,348
Бабло: $470735
|
Цитата:
Сообщение от sergeospb
венда и форки вещи несовместимые, только posix
|
а, может, что-то про винду и не подумал
на nix системах сравнивал форки и курл-мультипоточность, разница очень большая. Форк выжырает всю память на сервере, а коннектов все равно мало. Курл же наоборот, копейки памяти позволили обслуживать очень много коннектов. Точные цифры не помню.
|
|
|
01.07.2010, 20:36
|
#18
|
Ниибаца крутой програмер
Регистрация: 04.08.2009
Сообщений: 904
Бабло: $177555
|
Цитата:
Сообщение от chesser
qazxcvbnm
никак,
curl используется для коннекта(мультипоточного если надо) к серверу по определенным протоколам. Использование его мультипоточности позволяет сократить время ожидание коннекта к серверу, что очень много времени отнимает, если коннектиться в один поток.
|
да уже понял ... вспомнил что курл ниибацо хорош для разных протоколов, а при обращении к локальным файлам никаких же протоколов не используется
хотя, если запустить сервер и обратиться к локальному адресу 127.0.0.1/script.php то таки работает
в пустых циклах от 0 до 10.000 по очереди скрипт (10 запросов) выполнялся почти минуту (core2duo e45)
а при 10 потоках за несколько секунд
так что работает ... просто я хотел без запуска сервера
|
|
|
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
|
Ниибаца крутой програмер
Регистрация: 04.08.2009
Сообщений: 904
Бабло: $177555
|
чтобы без запуска сервера можно exec'ом открывать экземпляры стороннего скрипта с определёнными параметрами и чтобы результаты этой промежуточной паралельной обработки записывались во временные файлы, а в основном скрипте, после exec'ов отслеживать появление этих файлов и считывать из них данные и обрабатывать информацию дальше
|
|
|
02.07.2010, 23:06
|
#21
|
автоматизирую интернеты
Регистрация: 05.07.2009
Адрес: chesser.ru
Сообщений: 3,348
Бабло: $470735
|
Цитата:
Сообщение от qazxcvbnm
чтобы без запуска сервера можно exec'ом открывать экземпляры стороннего скрипта с определёнными параметрами и чтобы результаты этой промежуточной паралельной обработки записывались во временные файлы, а в основном скрипте, после exec'ов отслеживать появление этих файлов и считывать из них данные и обрабатывать информацию дальше
|
exec - это обычный exec() ? - не будет работать параллельно, т.к. главный скрипт будет ждать пока отработает каждый из запущенных exec'ов.
То, о чем ты говоришь, это и есть форк(ну или что-то такое) - когда главный процесс запускает подпроцессы, которые почти являются отдельными скриптами.
|
|
|
|