2012-10-11 43 views
4

我在製作命令行應用程序。我需要通過捲曲同時發出多個POST請求我在程序執行日誌之後 - 這意味着傳出請求都必須發送會話ID等使用POST的異步cURL

事件鏈如下:

  1. 我打開卷曲連接curl_init
  2. 我用curl_exec登錄遠程站點發送POST請求並獲取返回的HTML代碼作爲響應
  3. 我同時向同一站點發送多個POST請求。

我在考慮使用類似的東西:

// Init connection 

$ch = curl_init(); 

// Set curl options 

curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookies.txt'); 
curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookies.txt'); 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); 
curl_setopt($ch, CURLOPT_POST, 1); 

// Perform login 

curl_setopt($ch, CURLOPT_URL, "http://www.mysite/login.php"); 
$post = array('username' => 'username' , 'password' => 'password'); 
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post)); 
$result = curl_exec($ch); 

// Send multiple requests after being logged on 

curl_setopt($ch, CURLOPT_TIMEOUT_MS, 1); 

for($i = 0 ; $i < 10 ; $i++){ 
    $post = array('myvar' => 'changing_value'); 
    curl_setopt($ch, CURLOPT_URL, 'www.myweb.ee/changing_url'); 
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post)); 
    curl_exec($ch); 
} 

但這似乎並沒有工作,因爲只有在循環中的第一個請求似乎被髮送。

使用curl_multi_init大概會一個解決方案,但我不知道如果我可以通過它同捲曲用更改後的選項爲每個處理多次。

我不需要從服務器的同時請求任何迴應,但是這將是真棒,如果它也可以以某種方式完成。

這將是完美的,如果有人可以把我在正確的方向如何做到這一點。

+0

從您展示的代碼來看,實際上應該可以工作。 –

+0

這會工作,但該請求將依次進行,通過使用curl_multi你可以一次發送的所有請求,然後處理所有結果,當他們完成 – ninaj

回答

5

你需要創建一個新的捲曲處理爲每一個請求,然後用http://www.php.net/manual/en/function.curl-multi-add-handle.php

這裏註冊是一些代碼,我撕掉了,並從我的代碼基礎改編,心裏有,你應該添加錯誤在那裏檢查。

function CreateHandle($url , $data) { 
    $curlHandle = curl_init($url); 

    $defaultOptions = array (
     CURLOPT_COOKIEJAR => 'cookies.txt' , 
     CURLOPT_COOKIEFILE => 'cookies.txt' , 

     CURLOPT_ENCODING => "gzip" , 
     CURLOPT_FOLLOWLOCATION => true , 
     CURLOPT_RETURNTRANSFER => true , 
     CURLOPT_POST => 1, 
     CURLOPT_POSTFIELDS => $data 
    ); 

    curl_setopt_array($curlHandle , $defaultOptions); 

    return $curlHandle; 
} 

function MultiRequests($urls , $data) { 
    $curlMultiHandle = curl_multi_init(); 

    $curlHandles = array(); 
    $responses = array(); 

    foreach($urls as $id => $url) { 
     $curlHandles[$id] = CreateHandle($url , $data[$id]); 
     curl_multi_add_handle($curlMultiHandle, $curlHandles[$id]); 
    } 

    $running = null; 
    do { 
     curl_multi_exec($curlMultiHandle, $running); 
    } while($running > 0); 

    foreach($curlHandles as $id => $handle) { 
     $responses[$id] = curl_multi_getcontent($handle); 
     curl_multi_remove_handle($curlMultiHandle, $handle); 
    } 
    curl_multi_close($curlMultiHandle); 

    return $responses; 
} 
+0

是的,這是我可能需要使用方式 - 重新構建系統一點點,並使所有請求運行在不同的捲曲對象上。 – Tauri28

+0

我添加了一些代碼來顯示curl_multi將如何工作 – ninaj

+0

如何識別捲曲對象,當我不能建立一個循環,等待被執行並完成了所有的查詢。我得到了這個循環,它完成所有工作,查看哪些查詢推送到多個對象,執行它們並查看它們是否完成。如果有一種方法可以將ID附加到由curl_init返回的curl句柄。 – Tauri28

2

有一個更快,更有效的選擇......不需要你使用任何捲曲在所有...

http://uk3.php.net/manual/en/book.pthreads.php http://pthreads.org

見github for pecl ....

我會說這個,file_get_contents看起來很吸引人,但是PHP從來沒有被設計成以這種方式運行線程,它的套接字層和類似的東西不會考慮消耗你可能會發現這是更好地的fopen和睡眠插圖中的小讀取以節省CPU使用率......但是你這樣做會好很多......這怎麼你做取決於你想奉獻的任務是什麼樣的資源?

+0

很好的解決方案運行一次吧!我希望有一些很好的例子,如何在Windows下運行PHP安裝庫,我發現這個項目[鏈接](http://sources.redhat.com/pthreads-win32/)。 – Tauri28

+1

有DLL文件下載在github ... https://github.com/krakjoe/pthreads/downloads安裝像任何其他PHP擴展... –