[譯]php和curl_multi_exec

Uchiha_Ponny發表於2019-02-16

本文是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的文件更加的完整。

相關文章