當前位置: 首頁> 最新文章列表> 如何在curl_multi_close 之前判斷請求是否已完成

如何在curl_multi_close 之前判斷請求是否已完成

gitbox 2025-05-12

在使用curl_multi_*系列函數進行並發請求時,我們通常會開啟多個curl句柄並將它們加入到一個curl_multi句柄中統一管理。
為了確保在調用curl_multi_close釋放資源之前,所有的請求都已經正確完成,我們需要合理地檢測每一個請求的執行狀態。本文將講解一種標準且可靠的方法來實現這一需求。

基本流程概述

通常我們會按照以下步驟來處理多個請求:

  1. 初始化多個curl單獨句柄。

  2. 將這些句柄添加到一個curl_multi句柄中。

  3. 使用curl_multi_exec不斷地執行請求。

  4. 使用curl_multi_select配合curl_multi_exec檢測是否有請求完成。

  5. 逐個移除已完成的請求句柄。

  6. 確保所有請求完成後,再調用curl_multi_close

下面是一個完整示例,假設我們需要請求多個URL(這里以https://gitbox.net/example1https://gitbox.net/example2舉例):

 <?php

// 初始化 cURL multi 句柄
$multiHandle = curl_multi_init();

// 存放各個 cURL 句柄的數組
$curlHandles = [];

// 要請求的 URL 列表
$urls = [
    'https://gitbox.net/example1',
    'https://gitbox.net/example2',
];

// 創建並添加每一個 cURL 句柄
foreach ($urls as $i => $url) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    curl_multi_add_handle($multiHandle, $ch);
    $curlHandles[$i] = $ch;
}

// 執行 multi 請求
$running = null;
do {
    $status = curl_multi_exec($multiHandle, $running);

    // 防止 CPU 空轉
    if ($status == CURLM_OK) {
        curl_multi_select($multiHandle);
    } else {
        break;
    }

    // 检查是否有已完成的請求
    while ($info = curl_multi_info_read($multiHandle)) {
        if ($info['msg'] == CURLMSG_DONE) {
            // 獲取完成的句柄
            $completedHandle = $info['handle'];

            // 獲取返回內容
            $response = curl_multi_getcontent($completedHandle);

            // 可在這里處理返回的數據
            echo "請求完成,返回數據長度:" . strlen($response) . PHP_EOL;

            // 移除並關閉已完成的句柄
            curl_multi_remove_handle($multiHandle, $completedHandle);
            curl_close($completedHandle);
        }
    }
} while ($running > 0);

// 最後關閉 multi 句柄
curl_multi_close($multiHandle);

關鍵點解釋

  • curl_multi_exec :推進並發請求的執行,返回當前仍在運行的連接數量。

  • curl_multi_select :用於阻塞等待活動連接,減少CPU 資源浪費。

  • curl_multi_info_read :檢測是否有請求完成,並可以一次性處理已完成的句柄。

  • 只有當$running == 0 ,並且所有子句柄都已經被移除並關閉後,才調用curl_multi_close

小提示

  • 如果請求很多,建議添加超時機制,以防某些請求長時間卡住。

  • curl_multi_select有時返回-1 ,在這種情況下需要使用usleep()進行小幅度等待,防止死循環。

簡單處理select返回-1的示例:

 if (curl_multi_select($multiHandle) == -1) {
    usleep(100);
}

這樣可以保證腳本更加健壯。

總結

在使用curl_multi_close之前,關鍵是確認所有子請求都已經完成並正確清理,以上的模式是通用且推薦的標準做法。
多了解curl_multi_*系列的行為,有助於寫出更高效、穩定的並發網絡請求代碼!