в общем мой вопрос касается сабжа -- есть какиенибуть нормальные схемы реализации многопоточности в php -- искал в нете но там одно извращенство типо создания нескольких сокетов и последовательного чтения из каждого и тд ну в общем если есть у когонить инфа желательно с примером - если будет
точно не знаю.... в любом случае два варианта если ты работаешь с сокетами 1.асинхронные сокеты (то что ты и сказал - перебирать); curl_multi_init(); 2.использовать библиотеки там есть многопроцессорность (никакой информации у меня нет,могу ошибаться) *** pcntl_fork()
Много порочность врятли получиться но есть два выхода что можно сделать и оба под php5... 1) Это использовать url_multi_exec PHP: <?php // create both cURL resources $ch1 = curl_init(); $ch2 = curl_init(); // set URL and other appropriate options curl_setopt($ch1, CURLOPT_URL, "http://www.google.com/"); curl_setopt($ch1, CURLOPT_HEADER, 0); curl_setopt($ch2, CURLOPT_URL, "http://www.php.net/"); curl_setopt($ch2, CURLOPT_HEADER, 0); //create the multiple cURL handle $mh = curl_multi_init(); //add the two handles curl_multi_add_handle($mh,$ch1); curl_multi_add_handle($mh,$ch2); $running=null; //execute the handles do { curl_multi_exec($mh,$running); } while ($running > 0); //close the handles curl_multi_remove_handle($mh,$ch1); curl_multi_remove_handle($mh,$ch1); curl_multi_close($mh); ?> 2) Рассмотри вот этот скрипт PHP: <?php if (!defined("MD_DEBUG")) define("MD_DEBUG", false); function get_chanked($stream) { $content = ""; do { $len = trim(fgets($stream, 10)); if (MD_DEBUG) echo "Find lable 0x$len<br>\n"; if ($len === false || !preg_match("|[0-9a-f]+|i", $len)) { if (MD_DEBUG) echo "Failure getting content<br>\n"; return ""; } else { $len = hexdec($len); if (MD_DEBUG) echo "Reading $len byte<br>\n"; } if ($len > 0) { $readed = 0; while($readed < $len + 2) { $buffer = fgets($stream); $readed += strlen($buffer); $content .= $buffer; } } } while($len > 0); return $content; } function MyDownload ($urls, $timeout = 30) { $streams = array(); $result = array(); foreach($urls as $url) { $host = parse_url($url, PHP_URL_HOST); if ($host === null) { if (MD_DEBUG) echo "Host in '$url' is not correct<br>\n"; continue; } $port = parse_url($url, PHP_URL_PORT); $stream = @stream_socket_client(// Если не удается законнектится то выводится Warning, а он нам тут совершенно не нужен "tcp://$host:".($port === null ? "80" : $port), $errno, $errstr, $timeout, STREAM_CLIENT_ASYNC_CONNECT|STREAM_CLIENT_CONNECT); // Асинхронное соединение, что бы не ждать коннекта... if ($errno > 0) { if (MD_DEBUG) echo "Error connectiong to $url. $errstr($errno)<br>\n"; // либо еще что-нибудь делаем. Пишем в логи итп... continue; } stream_set_blocking($stream, 0); // Для всех потоков ставим режим non-blocking, что бы не ждать когда данные будут доступны для чтения/записи $streams[$url] = $stream; } $toException = $toRead = $toWrite = $streams; // Два массива потоков, для чтения и для записи. Для чтения можно сразуже задавать, т.к. все равно они не будут доступны пока не будет послан запрос do { $rStreams = $toRead; $wStreams = $toWrite; $eStreams = $toException; $num = @stream_select($rStreams, $wStreams, $eStreams, 0); // Выбираем какой-нибудь поток. Последний параметр 0 - не ждать таймаута if ($num > 0) // Если $num == 0, то можно добавить в общий массив новых потоков, что бы не stream_select не простаивал, но я не стал этого делать { if (count($wStreams) > 0) { foreach($wStreams as $write) { $url = array_search($write, $streams); $host = parse_url($url, PHP_URL_HOST); $request = "GET $url HTTP/1.1\r\nAccept: */*\r\nnAccept-Language: en-us\r\nPragma: no-cache\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 6.0)\r\nHost: $host\r\nConnection: Close\r\n\r\n"; if (MD_DEBUG) echo "Sending request for $url<br>\n$request"; fwrite($write, $request); unset($toWrite[array_search($write, $toWrite)]); // Запрос послан, больше не надо выбирать поток для записи } } if (count($rStreams) > 0) { foreach($rStreams as $read) { $url = array_search($read, $streams); $key = array_keys ($urls, $url); $key = $key[0]; if (MD_DEBUG) echo "Getting data for $url<br>\n"; $isChunk = false; $charset = ""; $result[$key][0] = ""; while(($header = fgets($read)) != "\r\n") { if (!(strpos($header, "Content-Type")===false)) if (!(strpos($header, "charset=")===false)) $charset = substr($header, strpos($header, "charset=")+8); else $charset = "default"; if (preg_match("|Transfer-Encoding:\s+chunked|i", $header)) $isChunk = true; } if ($isChunk) $result[$key][0] = get_chanked($read); else while (!feof($read)) $result[$key][0] .= fread($read, 1024); $result[$key][1] = $charset; unset($toRead[array_search($read, $toRead)]); // Ответ получен, поток не нужен больше } } if (count($eStreams) > 0) { foreach($eStreams as $exception) { $url = array_search($exception, $streams); if (MD_DEBUG) echo "Fail getting data for $url.<br>\n"; // Здесь так же кричим, что сервер вернул не то что ожидали и выкидываем этот поток из стека } unset($toRead[array_search($exception, $toRead)]); unset($toWrite[array_search($exception, $toWrite)]); unset($toException[array_search($exception, $toException)]); } } } while(count($toRead) > 0); // Читать нечего больше return $result; } $urls = array( "yandex"=>"http://www.yandex.ru/yandsearch?text=Превед", "whois"=>"http://www.service-whois.ru/?domain=mail.ru" ); $sites = MyDownload ($urls); $yandex1 = $sites["yandex"][0]; $yandex2 = $sites["yandex"][1]; ?> Даный скрипт будет работать только в php5, не много поточность... но работает быстро и эффективно...
Второй пример можно переделать под php 4, заменив работу функции stream_socket_client на fsockopen или Socket P.S. Вот уже есть готовый класс для работы с потоками http://multi-downoader.googlecode.com/svn/trunk/Downloader/
тема обсуждалась http://forum.antichat.ru/showthread.php?p=200343 и еще, СТАНДАРТНЫХ средств в пхп для многопоточности нет. но если вам необходимо качественное (все приведенные методы медленные и в общем случае нерабочие) решение, то теоретически можно написать свой модуль. а запускать функции через это http://man.chinaunix.net/develop/php/php_manual_zh/html/zend.calling-user-functions.html к сожалению как устроены переменные в пхп не знаю, поэтому утвержадть о работоспособности такого способа не могу.
ядро ОС перебирает готовые потоки, выделяя каждому квант времени. утверждение неверно =))) ( расценивать как шутку )
Многопоточность в PHP есть! Почему всё время забывают про pcntl_fork? Другое дело, что такое возможно реализовать только на Unix платформе, и если PHP включён не модулем, а как CGI.
>Почему всё время забывают про pcntl_fork? Потому-что в среднем php процесс занимает 16мб памяти и можно посчитать на сколько хватит памяти, если форкать много раз
2groundhog >>СТАНДАРТНЫХ средств в пхп для многопоточности нет и еще, поток это единица процесса, адресное пространство, за исключением стека и регистров, что для php не надо, одно и это в общем-то выгодное для определенных задач отличие от двух родственных процессов, поэтому если ищут именно решение для организации многопоточной программы не нужно давать решение для другой задачи.
Бред какой-то... Это вопрос конфигурации. ТС не ставил определённой задачи, а искал метод реализации - я его и предоставил.
нер, про матчасть стоит почитать имхо тебе. http://en.wikipedia.org/wiki/Light-weight_process читай это и все ссылки из See Also