<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Работа для  программистов &#187; curl</title>
	<atom:link href="http://job-interview.ru/articles/post/tag/curl/feed" rel="self" type="application/rss+xml" />
	<link>http://job-interview.ru/articles</link>
	<description>вакансии, вопросы, статьи</description>
	<lastBuildDate>Thu, 29 Mar 2012 20:53:41 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>&#8220;Многопоточность&#8221; в PHP (curl)</title>
		<link>http://job-interview.ru/articles/post/67</link>
		<comments>http://job-interview.ru/articles/post/67#comments</comments>
		<pubDate>Thu, 09 Jul 2009 07:09:35 +0000</pubDate>
		<dc:creator></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[curl]]></category>
		<category><![CDATA[многопоточность]]></category>
		<category><![CDATA[мультизапросы]]></category>

		<guid isPermaLink="false">/articles/?p=67</guid>
		<description><![CDATA[Использование библиотеки curl.
Эта статья является первой из серии &#8220;Многопоточность&#8221; в PHP

Curl – это библиотека, позволяющая подсоединяться к разным серверам по разным протоколам. Обладает удобством в работе и способностью гибко настраиваться.
Curl реализует механизм множественных запросов, или мультизапросов. Его принцип заключается в том, что посылается несколько запросов, при этом перед отправкой следующего не ожидается ответ на предыдущий.

Используем [...]]]></description>
			<content:encoded><![CDATA[<h3>Использование библиотеки curl.</h3>
<p>Эта статья является первой из серии <a href="/articles/post/62" target="_blank">&#8220;Многопоточность&#8221; в PHP</a></p>
<p>
<strong>Curl</strong> – это библиотека, позволяющая подсоединяться к разным серверам по разным протоколам. Обладает удобством в работе и способностью гибко настраиваться.<br />
Curl реализует механизм <em>множественных запросов</em>, или <em>мультизапросов</em>. Его принцип заключается в том, что посылается несколько запросов, при этом перед отправкой следующего не ожидается ответ на предыдущий.
</p>
<p>Используем это в нашем примере <strong>скачивания нескольких страниц</strong>.
</p>
<p>Рассмотрим сначала процесс <em>скачивания содержимого с одного url</em>. </p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000088;">$url</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'mail.ru'</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">// инициализация сеанса curl</span>
<span style="color: #000088;">$ch</span> <span style="color: #339933;">=</span> <span style="color: #990000;">curl_init</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'http://'</span><span style="color: #339933;">.</span><span style="color: #000088;">$url</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">// curl_exec будет возвращать результат</span>
<span style="color: #990000;">curl_setopt</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ch</span><span style="color: #339933;">,</span> CURLOPT_RETURNTRANSFER<span style="color: #339933;">,</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">// не будет возвращаться http-заголовок</span>
<span style="color: #990000;">curl_setopt</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ch</span><span style="color: #339933;">,</span> CURLOPT_HEADER<span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">// загрузка страницы и выдача её браузеру</span>
<span style="color: #000088;">$content</span> <span style="color: #339933;">=</span> <span style="color: #990000;">curl_exec</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ch</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">// завершение сеанса и освобождение ресурсов</span>
<span style="color: #990000;">curl_close</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ch</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>
Здесь <em>функцией curl_init</em> мы инициализируем сеанс curl и в качестве параметра передаем урл страницы, которую хотим скачать. Далее первым вызовом <em>функции curl_setopt</em> говорим, что результат надо вернуть, а не вывести в браузер, и вторым запрещаем передачу нам http-ответа сервера. curl_setopt принимаюет в качестве параметров дескриптор соединения $ch, название опции и ее значение соответственно. С помощью curl_setopt можно задать много параметров для более тонкого управления соединением, подробнее читайте в <a href="http://php.net/curl" target="_blank">мануале</a> к этой библиотеке. Затем <em>функцией curl_exec</em> производим собственно скачивание и в завершении закрываем соединение &#8211; <em>curl_close</em>. В переменной $content у нас теперь находится код страницы, указанной в $url.
</p>
<p>А сейчас давайте попробуем <strong>скачать сразу несколько страниц</strong> (основа примера взята из документации на php.net):
</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// страницы, содержимое которых надо получить</span>
<span style="color: #000088;">$urls</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'yandex.ru'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'google.ru'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'mail.ru'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'rambler.ru'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// инициализируем &quot;контейнер&quot; для отдельных соединений (мультикурл)</span>
<span style="color: #000088;">$cmh</span> <span style="color: #339933;">=</span> <span style="color: #990000;">curl_multi_init</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// массив заданий для мультикурла</span>
<span style="color: #000088;">$tasks</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">// перебираем наши урлы</span>
<span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$urls</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$url</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #666666; font-style: italic;">// инициализируем отдельное соединение (поток)</span>
	<span style="color: #000088;">$ch</span> <span style="color: #339933;">=</span> <span style="color: #990000;">curl_init</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'http://'</span><span style="color: #339933;">.</span><span style="color: #000088;">$url</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #666666; font-style: italic;">// если будет редирект - перейти по нему</span>
	<span style="color: #990000;">curl_setopt</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ch</span><span style="color: #339933;">,</span> CURLOPT_FOLLOWLOCATION<span style="color: #339933;">,</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #666666; font-style: italic;">// возвращать результат</span>
	<span style="color: #990000;">curl_setopt</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ch</span><span style="color: #339933;">,</span> CURLOPT_RETURNTRANSFER<span style="color: #339933;">,</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #666666; font-style: italic;">// не возвращать http-заголовок</span>
	<span style="color: #990000;">curl_setopt</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ch</span><span style="color: #339933;">,</span> CURLOPT_HEADER<span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #666666; font-style: italic;">// таймаут соединения</span>
	<span style="color: #990000;">curl_setopt</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ch</span><span style="color: #339933;">,</span> CURLOPT_CONNECTTIMEOUT<span style="color: #339933;">,</span> <span style="color: #cc66cc;">10</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #666666; font-style: italic;">// таймаут ожидания</span>
	<span style="color: #990000;">curl_setopt</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ch</span><span style="color: #339933;">,</span> CURLOPT_TIMEOUT<span style="color: #339933;">,</span> <span style="color: #cc66cc;">10</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #666666; font-style: italic;">// добавляем дескриптор потока в массив заданий</span>
	<span style="color: #000088;">$tasks</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$url</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$ch</span><span style="color: #339933;">;</span>
	<span style="color: #666666; font-style: italic;">// добавляем дескриптор потока в мультикурл</span>
	<span style="color: #990000;">curl_multi_add_handle</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$cmh</span><span style="color: #339933;">,</span> <span style="color: #000088;">$ch</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// количество активных потоков</span>
<span style="color: #000088;">$active</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">// запускаем выполнение потоков</span>
<span style="color: #b1b100;">do</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$mrc</span> <span style="color: #339933;">=</span> <span style="color: #990000;">curl_multi_exec</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$cmh</span><span style="color: #339933;">,</span> <span style="color: #000088;">$active</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span> 
<span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$mrc</span> <span style="color: #339933;">==</span> CURLM_CALL_MULTI_PERFORM<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// выполняем, пока есть активные потоки</span>
<span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$active</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$mrc</span> <span style="color: #339933;">==</span> CURLM_OK<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #666666; font-style: italic;">// если какой-либо поток готов к действиям</span>
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">curl_multi_select</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$cmh</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #666666; font-style: italic;">// ждем, пока что-нибудь изменится</span>
		<span style="color: #b1b100;">do</span> <span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$mrc</span> <span style="color: #339933;">=</span> <span style="color: #990000;">curl_multi_exec</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$cmh</span><span style="color: #339933;">,</span> <span style="color: #000088;">$active</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #666666; font-style: italic;">// получаем информацию о потоке</span>
			<span style="color: #000088;">$info</span> <span style="color: #339933;">=</span> <span style="color: #990000;">curl_multi_info_read</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$cmh</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #666666; font-style: italic;">// если поток завершился</span>
			<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$info</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'msg'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> CURLMSG_DONE<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
				<span style="color: #000088;">$ch</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$info</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'handle'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
				<span style="color: #666666; font-style: italic;">// ищем урл страницы по дескриптору потока в массиве заданий</span>
				<span style="color: #000088;">$url</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_search</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ch</span><span style="color: #339933;">,</span> <span style="color: #000088;">$tasks</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				<span style="color: #666666; font-style: italic;">// забираем содержимое</span>
				<span style="color: #000088;">$tasks</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$url</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">curl_multi_getcontent</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ch</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				<span style="color: #666666; font-style: italic;">// удаляем поток из мультикурла</span>
				<span style="color: #990000;">curl_multi_remove_handle</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$cmh</span><span style="color: #339933;">,</span> <span style="color: #000088;">$ch</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				<span style="color: #666666; font-style: italic;">// закрываем отдельное соединение (поток)</span>
				<span style="color: #990000;">curl_close</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ch</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #009900;">&#125;</span>
		<span style="color: #009900;">&#125;</span>
		<span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$mrc</span> <span style="color: #339933;">==</span> CURLM_CALL_MULTI_PERFORM<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// закрываем мультикурл</span>
<span style="color: #990000;">curl_multi_close</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$cmh</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>Код подробно откомментирован, но давайте разберем все по порядку.<br />
В 7 строчке мы инициализируем контейнер для отдельных соединений curl (далее я буду называть его <em>мультикурл</em>), именно он позволит нам проводить операции с ними <em>параллельно</em>.<br />
Далее в цикле инициализируем соединение (назовем его <em>поток</em>) для каждого урла из нашего массива, попутно добавляя его в мультикурл и в массив заданий $tasks. $tasks – массив, в котором ключами являются адреса наших страниц, а значениями – соответствующие дескрипторы curl. <em>Функция curl_multi_add_handle</em> добавляет к дескриптору нашего мультизапросного соединения отдельное созданное соединение.</p>
<p>
В 34 строке запускается цикл для начала работы нашего мультикурла. <em>Функция curl_multi_exec</em> <strong>одновременно отправляет на выполнение все объявленные потоки</strong>, при этом в переменную $active заносится количество выполняемых потоков.
</p>
<p>
В основном цикле, начинающемся на 40 строчке, происходят главные действия. Он выполняется до тех пор, пока есть незавершенные потоки или пока не произошла ошибка. В 42 строке вызывается <em>функция curl_multi_select</em>, которая проверяет готовность какого-либо из потоков к дальнейшим действиям с ним. Затем, в 47 строке, <em>функцией curl_multi_info_read</em> получаем информацию о потоке. Но так как curl_multi_info_read обновляет возвращаемую информацию только после вызова curl_multi_exec, сделаем это в строке 45.
</p>
<p>Функция curl_multi_info_read возвращает массив, в котором нас интересуют ключи &#8216;msg&#8217; и &#8216;handle&#8217;. По &#8216;msg&#8217; мы проверяем, выполнился ли поток, а по &#8216;handle&#8217; узнаем его дескриптор. Получив дескриптор, ищем по массиву заданий, к какому урлу он относится и записываем вместо него вожделенное содержимое страницы, получаемое <em>функцией curl_multi_getcontent</em>.<br />
Теперь, когда данный поток выполнил свою задачу, удаляем его из мультикурла, а потом закрываем самого.</p>
<p>После завершения всех потоков <em>функцией curl_multi_close</em> закрываем мультикурл.</p>
<p>Сейчас в массиве заданий $tasks находятся html-коды заданных страниц.</p>
<p>Надеюсь, после прочтения статьи стало немного понятнее, как можно реализовать выполнение &#8220;многопоточных&#8221; запросов на PHP.</p>
<p>В <a href="/articles/post/92" target="_blank">следующей статье</a> рассмотрим использование stream-функций для подобных целей.</p>
]]></content:encoded>
			<wfw:commentRss>http://job-interview.ru/articles/post/67/feed</wfw:commentRss>
		<slash:comments>17365</slash:comments>
		</item>
	</channel>
</rss>
