Вход Регистрация
Существует ли в PHP многопоточность? (оценка: 0)
PHP относится к языкам, в которых поддержка многопоточности отсутствует. Но, есть немало задач, в которых она была бы очень полезна. В большинстве случаев вам не нужно порождать и создавать новых потоков вообще и можно получить отличную производительность и без этого.

Сокеты
Очень полезная штука, когда вам надо дёргать чужие страницы или просто посылать запросы к другим сайтам.

Недавно поступил заказ на скрипт, который будет дёргать информацию с одного сайта, сохранять в базу, а потом переносить на другой. Порой скрипт делает запросы к 100+ страницам. Если этот скрипт бы выполнялся последовательно, то заняло бы много времени.

В этом деле поможет функция stream_socket_client

Прелесть в том, что, создавая запросы к сайтам этой функцией в асинхронном режиме, нам не придётся ждать ответа. Задача состоит из двух частей.

Создать сокеты
  1. $flag = STREAM_CLIENT_ASYNC_CONNECT | STREAM_CLIENT_CONNECT;
  2. $sockets = array();
  3. $id = 0;
  4. $timeout = 60;
  5. $convenient_read_block = 8192;
  6. $result = array();
  7. $url = array();
  8. for ($i = $this - > beg_ID; $i <= $this - > end_ID; ++$i) {
  9. $fp = stream_socket_client('tcp://'.$host.
  10. ':'.$this - > port, $err, $errstr, 8, $flag);
  11. if (!$fp) {
  12. echo 'httpPost error: '.$errstr;
  13. return NULL;
  14. } else {
  15. $sockets[$id++] = $fp;
  16. $url[$id - 1] = $i;
  17. }
  18. }



Как видно, создаются сокеты и ссылки на них сохраняются в массиве $sockets. Теперь необходимо организовать прослушку ответов.

Ждём ответа

В некоторых источниках видел исходники, где функция на запись в сокет вызывается сразу после создания(применяли к $fp). На самом деле необходимо организовать прослушку на готовность сокета и к чтению, и к записи.

  1. //создаём массивы сокетов для прослушки
  2. $toRead = $toWrite = $sockets;
  3. //пока есть сокеты, чтение с которых мы ждём
  4. while (count($toRead) > 0) {
  5. $read=$toRead;
  6. $write=$toWrite;
  7. stream_select($read, $write, $e=null, $timeout);
  8. //есть сокеты, готовые к записи
  9. if (count($write)) {
  10. foreach ($write as $w) {
  11. $id=array_search($w, $sockets);
  12. //$query="GET /product.php?pid=PD".$id." HTTP/1.0\r\n".
  13. $query="GET /product.php?pid=PD0".$url[$id]." HTTP/1.0\r\n". "Host: ".$host."\r\n". "User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1\r\n". "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*\/*;q=0.8". "Accept-Language: ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3\r\n". "Accept-Encoding: gzip, deflate\r\n". "Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7\r\n". "Connection: close\r\n\r\n";
  14. fwrite($w, $query);
  15. unset($toWrite[array_search($w, $toWrite)]);
  16. }
  17. }
  18. //есть сокеты, готовые к чтению
  19. if (count($read)) {
  20. foreach ($read as $r) {
  21. $id=array_search($r, $sockets);
  22.  
  23. if(!isset($result[$id])) $result[$id]='';
  24. $data=fread($r, $convenient_read_block);
  25.  
  26. if (strlen($data) == 0) {
  27. fclose($r);
  28. unset($toRead[array_search($r, $toRead)]);
  29. } else {
  30. $result[$id] .= $data;
  31. }
  32. }
  33. }
  34. }


Мы используем функцию stream_select() для ожидания возникновения событий на открытых сокетах. Вы можете ожидать готовности чтения, записи или исключительных событий (параметр первый, второй и третий соответственно). stream_select() будет ждать $timeout секунд пока событие не появится – когда же это случится, функция будет модифицировать массивы, которые Вы ей передали, так что они будут содержать идентификаторы сокетов, удовлетворяющих Вашему критерию.

Ну, как примечание, скажу, что доступна эта прелесть с PHP 5.
Автор: * -=(C)DRU987=- (Dev) / 08.03.2016 в 12:23
Просмотров: 374
ТОП блогов | поиск | все блоги
Онлайн: 3
Реклама