本文是PHP and curl_multi_exec的翻譯
這篇文章闡述瞭如何從curl_multi
控制程式碼獲取資料。不久前,我將這段程式碼片段貼到了一個更大的示例程式碼中:
<?php
$active = NULL;
do {
$ret = curl_multi_exec($multi, $active);
} while ($ret == CURLM_CALL_MULTI_PERFORM);
while ($active && $ret == CURLM_OK) {
if (curl_multi_select($multi) != -1) {
do {
$mrc = curl_multi_exec($multi, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
}
?>
我之前沒有真的去查過文件試圖理解過它。所以這段程式碼讓我感到困惑。現在我來解釋下它都做了什麼。
首先,這裡有兩個外層的迴圈。第一個負責清除curl快取。第二個負責等待更多的資料,並且獲取到這些資料。這就是一個典型的阻塞I/O例子。我們阻塞住剩下程式的執行直到網路I/O的結束。儘管這不是處理網路I/O最合適的方法,但對於單程式、同步的PHP,這實際上是我們僅有的選擇。
讓我們先來看下第一層迴圈:
<?php
$active = NULL;
do {
$ret = curl_multi_exec($multi, $active);
} while ($ret == CURLM_CALL_MULTI_PERFORM);
?>
curl_multi_exec
嘗試從multi控制程式碼中獲取寫資料。$multi
是之前呼叫curl_multi_init()
方法產生的控制程式碼,$active
和$ret
都是整型的值。curl_multi_exec()
把$active
設為正在處理的控制程式碼個數。換句話說,如果你正在用這個控制程式碼請求5個URL,那麼curl_multi_exec
將返回5當它正在處理所有的5個URL(應該是指curl_multi_exec
設$active
為5),然後當每個請求結束時,這個數字將會逐漸減少直到0。
$ret
是如下值的一種:
-
CURLM_CALL_MULTI_PERFORM
(-1):這意味著你需要再次呼叫curl_multi_exec()
,因為仍有資料可供處理。 -
CURLM_OK
(0):如文件中所說:“都好了”。這意味著可能有更多的資料,但還沒有到呢。 - 錯誤碼中的一個:
CURLM_BAD_HANDLE
,CURLM_OUT_OF_MEMORY
,CURLM_INTERNAL_ERROR
,CURLM_BAD_SOCKET
。所有這些表明我們需要停止處理。
所以當我們正在執行第一層迴圈,唯一需要我們繼續迭代的情況就是CURLM_CALL_MULTI_PERFORM
。
現在,對於一些相當小的情況,第一層迴圈就是你所需要的。然而通常的情況是,第一層迴圈會返回CURL_OK
來表明還會有更多的資料,但是這些資料還沒有在網路上傳輸過來呢。
我們需要wait。
這時候我們就需要第二層迴圈:
<?php
while ($active && $ret == CURLM_OK) {
if (curl_multi_select($multi) != -1) {
do {
$mrc = curl_multi_exec($multi, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
}
?>
這層迴圈是說…
(while): 只要有活躍的連線,一切還看著都OK…
(if) 如果網路socket還有些資料…
(do/while) 只要系統告訴我們要一直去獲取資料,我們就處理吧
所以第二層迴圈負責檢查套接字直到一切就緒。
PHP手冊對這些東西的細節有稍微的介紹,但是libcurl C的文件更加的完整。