使用POST的异步cURL

时间:2012-10-11 12:42:17

标签: php curl http-post

我正在制作命令行应用程序。在执行登录过程后,我需要同时通过cURL发送多个POST请求 - 这意味着传出请求必须发送会话ID等。

事件链如下:

  1. 我用curl_init打开cURL连接
  2. 我使用curl_exec登录远程站点发送POST请求,并返回HTML代码作为响应
  3. 我同时向同一网站发送多个POST请求。
  4. 我在考虑使用类似的东西:

    // 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可能是一个解决方案,但我不知道我是否可以多次传递相同的cURL句柄,每个句子都有更改的选项。

    我不需要服务器对这些同步请求做出任何响应,但如果它也能以某种方式完成它会很棒。

    如果有人能够把我推向正确的方向,那将是完美的。

2 个答案:

答案 0 :(得分:5)

您需要为每个请求创建一个新的curl句柄,然后将其注册到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;
}

答案 1 :(得分:2)

这是一个更快,更有效的选择......根本不需要你使用任何卷曲...

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

请参阅github获取最新的源代码,发布于pecl ....

我会这么说,file_get_contents看起来很吸引人,但是PHP从未被设计成以这种方式运行线程,它的套接字层等没有考虑消费你可能会发现它更好在少量读取之间进行打开和睡眠以节省CPU使用量...但是你这样做会好得多......而你如何做到这取决于你想要为这项任务投入什么样的资源......