當前位置: 首頁> 最新文章列表> 使用curl_multi_close 在異步請求中避免重複關閉連接

使用curl_multi_close 在異步請求中避免重複關閉連接

gitbox 2025-05-13

在PHP 中, cURL是一個強大的庫,它允許我們通過多種協議發送請求,例如HTTP、HTTPS、FTP 等。而curl_multi_*系列函數允許我們同時發出多個異步請求,從而提高性能,減少請求時間,特別是在需要發起多個HTTP 請求時,異步請求非常有用。

然而,在使用curl_multi_*函數進行異步請求時,有一個常見的坑:重複關閉連接。當我們通過curl_multi_close函數關閉cURL 會話時,如果沒有正確管理連接,可能會導致一些連接在未被正確關閉前被重複關閉,從而引發錯誤或內存洩漏。

本文將帶您了解如何在PHP 中正確使用curl_multi_close來管理異步請求,並避免重複關閉連接的問題。

一、使用curl_multi_*函數的基本步驟

首先,我們來看一下如何使用PHP 的curl_multi_*系列函數發起多個異步請求。以下是一個基本示例:

 <?php
// 創建多個 cURL 會話
$ch1 = curl_init();
$ch2 = curl_init();

// 設定 cURL 請求選項
curl_setopt($ch1, CURLOPT_URL, 'https://gitbox.net/api/endpoint1');
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch2, CURLOPT_URL, 'https://gitbox.net/api/endpoint2');
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);

// 創建 cURL 多重句柄
$mh = curl_multi_init();

// 將每個 cURL 會話加入多重句柄
curl_multi_add_handle($mh, $ch1);
curl_multi_add_handle($mh, $ch2);

// 執行異步請求
do {
    $status = curl_multi_exec($mh, $active);
} while ($active);

// 獲取每個請求的返回結果
$response1 = curl_multi_getcontent($ch1);
$response2 = curl_multi_getcontent($ch2);

// 輸出結果
echo "Response 1: " . $response1 . "\n";
echo "Response 2: " . $response2 . "\n";

// 关闭會話
curl_multi_remove_handle($mh, $ch1);
curl_multi_remove_handle($mh, $ch2);
curl_multi_close($mh);
curl_close($ch1);
curl_close($ch2);
?>

在這個例子中,我們創建了兩個cURL 會話並設置了請求URL,使用curl_multi_*函數同時發出兩個異步請求。 curl_multi_exec會一直運行,直到所有請求完成。然後我們使用curl_multi_getcontent獲取返回結果,最後關閉所有會話。

二、避免重複關閉連接的問題

在上面的代碼中,我們使用了curl_multi_close來關閉cURL 多重句柄,使用curl_close關閉每個單獨的cURL 會話。這是一個常見的做法,但需要注意的是, curl_multi_close只負責關閉多重句柄,不會關閉每個會話句柄。所以每個curl_*會話在關閉curl_multi_close後,仍然需要通過curl_close來關閉。

問題:如果你在某些情況下重複調用了curl_closecurl_multi_close ,就可能出現連接被重複關閉的問題。為了避免這種情況,我們可以採取以下兩種方法:

  1. 確保每個句柄只關閉一次<br> 在循環或處理過程中,我們可能會不小心重複關閉某些會話為避免這種問題,可以在關閉時做一個標記,確保每個句柄只關閉一次。

  2. 先移除句柄再關閉<br> 使用curl_multi_remove_handle來移除句柄,確保每個句柄在關閉時已從多重句柄中移除這樣可以避免調用curl_multi_close時會出現已關閉的句柄。

三、改進的代碼示例

為了避免重複關閉連接,我們對代碼進行改進:

 <?php
// 創建多個 cURL 會話
$ch1 = curl_init();
$ch2 = curl_init();

// 設定 cURL 請求選項
curl_setopt($ch1, CURLOPT_URL, 'https://gitbox.net/api/endpoint1');
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch2, CURLOPT_URL, 'https://gitbox.net/api/endpoint2');
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);

// 創建 cURL 多重句柄
$mh = curl_multi_init();

// 將每個 cURL 會話加入多重句柄
curl_multi_add_handle($mh, $ch1);
curl_multi_add_handle($mh, $ch2);

// 執行異步請求
do {
    $status = curl_multi_exec($mh, $active);
} while ($active);

// 獲取每個請求的返回結果
$response1 = curl_multi_getcontent($ch1);
$response2 = curl_multi_getcontent($ch2);

// 輸出結果
echo "Response 1: " . $response1 . "\n";
echo "Response 2: " . $response2 . "\n";

// 移除句柄后再关闭會話
curl_multi_remove_handle($mh, $ch1);
curl_multi_remove_handle($mh, $ch2);

// 正確關閉
curl_multi_close($mh);
curl_close($ch1);
curl_close($ch2);
?>

四、總結

  1. 使用curl_multi_*函數可以有效地發起多個異步請求,提高性能。

  2. 在關閉cURL 會話時,務必要先用curl_multi_remove_handle移除會話,然後再調用curl_multi_close

  3. 每個cURL 會話都應在關閉前通過curl_close關閉,避免在curl_multi_close中重複關閉。

通過正確管理連接的關閉,我們能夠避免連接被重複關閉,確保代碼更加穩定高效。