Форум АНТИЧАТ

Форум АНТИЧАТ (https://forum.antichat.xyz/index.php)
-   PHP, PERL, MySQL, JavaScript (https://forum.antichat.xyz/forumdisplay.php?f=37)
-   -   многопоточность в php (https://forum.antichat.xyz/showthread.php?t=52183)

genom-- 27.10.2007 22:57

многопоточность в php
 
в общем мой вопрос касается сабжа -- есть какиенибуть нормальные схемы реализации многопоточности в php -- искал в нете но там одно извращенство типо создания нескольких сокетов и последовательного чтения из каждого и тд

ну в общем если есть у когонить инфа желательно с примером - если будет ;)

Stefun 27.10.2007 23:18

Первый раз слышу что в пхп можно сделать многопоточность, мда...
В пхп нельзя это реализовать

inv 27.10.2007 23:36

точно не знаю....
в любом случае два варианта
если ты работаешь с сокетами
1.асинхронные сокеты (то что ты и сказал - перебирать); curl_multi_init();
2.использовать библиотеки там есть многопроцессорность (никакой информации у меня нет,могу ошибаться)

***
pcntl_fork()

EST a1ien 27.10.2007 23:36

Думаю что кроме того сто ты привел
Цитата:

там одно извращенство типо создания нескольких сокетов и последовательного чтения из каждого и тд
Врядли чтото прокатит

KSURi 27.10.2007 23:38

пора бы уже знать, что НЕТ

genom-- 27.10.2007 23:42

я знаю что нет -- но тем не менее мб ченить кроме этих сокетов -- придумали уже

KSURi 28.10.2007 02:06

Пул неблокирующих сокетов - это не многопоточность
Ничего не придумали и врядли придумают

Isis 28.10.2007 02:51

перебирать != многопоточность

DIAgen 28.10.2007 11:39

Много порочность врятли получиться но есть два выхода что можно сделать и оба под 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($ch1CURLOPT_URL"http://www.google.com/");
curl_setopt($ch1CURLOPT_HEADER0);
curl_setopt($ch2CURLOPT_URL"http://www.php.net/");
curl_setopt($ch2CURLOPT_HEADER0);

//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($stream10));
      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($urlPHP_URL_HOST);
       if (
$host === null)
       {
          if (
MD_DEBUG) echo "Host in '$url' is not correct<br>\n";
          continue;
       }
       
$port parse_url($urlPHP_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($stream0); // Для всех потоков ставим режим non-blocking, что бы не ждать когда данные будут доступны для чтения/записи
       
$streams[$url] = $stream;
    }
    
$toException $toRead $toWrite $streams// Два массива потоков, для чтения и для записи. Для чтения можно сразуже задавать, т.к. все равно они не будут доступны пока не будет послан запрос
    
do
    {
       
$rStreams $toRead;
       
$wStreams $toWrite;
       
$eStreams $toException;
       
$num = @stream_select($rStreams$wStreams$eStreams0); // Выбираем какой-нибудь поток. Последний параметр 0 - не ждать таймаута 
    
       
if ($num 0// Если $num == 0, то можно добавить в общий массив новых потоков, что бы не stream_select не простаивал, но я не стал этого делать
       
{
          if (
count($wStreams) > 0)
          {
             foreach(
$wStreams as $write)
             {
                
$url array_search($write$streams);
                
$host parse_url($urlPHP_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($headerstrpos($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($read1024);
                
$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, не много поточность... но работает быстро и эффективно...

genom-- 28.10.2007 11:47

лан спс всем -- будем думать

DIAgen 28.10.2007 11:48

Второй пример можно переделать под php 4, заменив работу функции stream_socket_client на fsockopen или Socket


P.S. Вот уже есть готовый класс для работы с потоками http://multi-downoader.googlecode.com/svn/trunk/Downloader/

ZaCo 28.10.2007 12:23

тема обсуждалась http://forum.antichat.ru/showthread.php?p=200343
и еще, СТАНДАРТНЫХ средств в пхп для многопоточности нет. но если вам необходимо качественное (все приведенные методы медленные и в общем случае нерабочие) решение, то теоретически можно написать свой модуль.
а запускать функции через это http://man.chinaunix.net/develop/php/php_manual_zh/html/zend.calling-user-functions.html
к сожалению как устроены переменные в пхп не знаю, поэтому утвержадть о работоспособности такого способа не могу.

_Great_ 28.10.2007 12:32

Цитата:

Сообщение от Isis
перебирать != многопоточность

ядро ОС перебирает готовые потоки, выделяя каждому квант времени. утверждение неверно =)))

( расценивать как шутку )

groundhog 28.10.2007 14:11

Многопоточность в PHP есть! Почему всё время забывают про pcntl_fork? Другое дело, что такое возможно реализовать только на Unix платформе, и если PHP включён не модулем, а как CGI.

fucker"ok 28.10.2007 14:49

>Почему всё время забывают про pcntl_fork?
Потому-что в среднем php процесс занимает 16мб памяти и можно посчитать на сколько хватит памяти, если форкать много раз :)

ZaCo 28.10.2007 14:56

2groundhog
>>СТАНДАРТНЫХ средств в пхп для многопоточности нет
и еще, поток это единица процесса, адресное пространство, за исключением стека и регистров, что для php не надо, одно и это в общем-то выгодное для определенных задач отличие от двух родственных процессов, поэтому если ищут именно решение для организации многопоточной программы не нужно давать решение для другой задачи.

groundhog 28.10.2007 15:06

Цитата:

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

Цитата:

Потому-что в среднем php процесс занимает 16мб памяти и можно посчитать на сколько хватит памяти, если форкать много раз
Это вопрос конфигурации. ТС не ставил определённой задачи, а искал метод реализации - я его и предоставил.

_Great_ 28.10.2007 15:17

Цитата:

Сообщение от fucker"ok
>Почему всё время забывают про pcntl_fork?
Потому-что в среднем php процесс занимает 16мб памяти и можно посчитать на сколько хватит памяти, если форкать много раз :)

вроде как в линуксе потоки реализованы как процессы.

nerezus 28.10.2007 15:41

Цитата:

Многопоточность в PHP есть! Почему всё время забывают про pcntl_fork?
Это не потоки. Учи матчасть.

Многопоточности в PHP нету и не будет. Тема закрыта.

_Great_ 28.10.2007 17:25

Цитата:

Сообщение от nerezus
Это не потоки. Учи матчасть.

Многопоточности в PHP нету и не будет. Тема закрыта.

нер, про матчасть стоит почитать имхо тебе.

http://en.wikipedia.org/wiki/Light-weight_process
читай это и все ссылки из See Also


Время: 22:47