0

I need to execute multiple request in parallel using cURL, but I need to do it against the same URL.

This is because is a SOAP webservice, I have a unique URL but I'll send different headers to receive multiple responses that I need.

I tried to make a curl_multi_exec, but I var_dump the $channels array and I receive only 1, I think is because cURL is re-using connections and so, I tried CURLOPT_FRESH_CONNECT and CURLOPT_FORBID_REUSE without success.

Any idea how to achieve it?

    $url = "http://myURL.com/SOAPWebservice.svc";
    $stationIds = array(207,303,305,195,204,205);//5,10);
    // 207,303,305,195,204,205,206,212,306,196,193,194,307,312,197,198,199,200,201,202,203,302,308,367,304,309,310,311

    $multi = curl_multi_init();
    $channels = array();

    // Loop through the URLs, create curl-handles
    // and attach the handles to our multi-request
    foreach ($stationIds as $stationId)
    {
        $soap_request =
            '<?xml version="1.0" encoding="UTF-8"?>
                <SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns6930="http://tempuri.org" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                    <SOAP-ENV:Body>
                        <GetStationById xmlns="http://tempuri.org/">
                            <StationID>' . $stationId . '</StationID>
                            <CityID>5</CityID>
                        </GetStationById>
                    </SOAP-ENV:Body>
                </SOAP-ENV:Envelope>';

        $header = array(
            "Content-type: text/xml;charset=\"utf-8\"",
            "Accept: text/xml",
            "Cache-Control: no-cache",
            "Pragma: no-cache",
            "SOAPAction: \"http://tempuri.org/IBLLStation/GetStationById\"",
            "Content-length: ".strlen($soap_request),
        );


        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL,            $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true );
        curl_setopt($ch, CURLOPT_POST,           true );
        curl_setopt($ch, CURLOPT_POSTFIELDS,     $soap_request);
        curl_setopt($ch, CURLOPT_HTTPHEADER,     $header);
        curl_setopt($ch, CURLOPT_FRESH_CONNECT,     TRUE);
        curl_setopt($ch, CURLOPT_FORBID_REUSE,     TRUE);

        curl_multi_add_handle($multi, $ch);

        $channels[$url] = $ch;
    }

    // While we're still active, execute curl
    $active = null;
    do {
        $mrc = curl_multi_exec($multi, $active);
    } while ($mrc == CURLM_CALL_MULTI_PERFORM);

    while ($active && $mrc == CURLM_OK) {
        // Wait for activity on any curl-connection
        if (curl_multi_select($multi) == -1) {
            continue;
        }

        // Continue to exec until curl is ready to
        // give us more data
        do {
            $mrc = curl_multi_exec($multi, $active);
        } while ($mrc == CURLM_CALL_MULTI_PERFORM);
    }

    // Loop through the channels and retrieve the received
    // content, then remove the handle from the multi-handle
    $StationsLastContact = "";
    // echo print_r($channels,TRUE);
    foreach ($channels as $channel) {
        $response = curl_multi_getcontent($channel);
        $startsAt           = strpos($response, "StationLastContact>") + strlen("StationLastContact>");
        $endsAt             = strpos($response, "<", $startsAt);
        $StationLastContact = substr($response, $startsAt, $endsAt - $startsAt);
        $StationLastContact .= "<br />";
        $StationsLastContact .= $StationLastContact;
        curl_multi_remove_handle($multi, $channel);
    }

    // Close the multi-handle and return our results
    curl_multi_close($multi);

    die($StationsLastContact);
1
  • You are overriding the handler i guess. Commented Dec 10, 2013 at 10:39

1 Answer 1

1

Check if the code below works. I just used a handler array.

var_dump($ch);

array(6) {
  [207]=>
  resource(3) of type (curl)
  [303]=>
  resource(4) of type (curl)
  [305]=>
  resource(5) of type (curl)
  [195]=>
  resource(6) of type (curl)
  [204]=>
  resource(7) of type (curl)
  [205]=>
  resource(8) of type (curl)
}


    $url = "http://myURL.com/SOAPWebservice.svc";
    $stationIds = array(207,303,305,195,204,205);//5,10);
    // 207,303,305,195,204,205,206,212,306,196,193,194,307,312,197,198,199,200,201,202,203,302,308,367,304,309,310,311

    $multi = curl_multi_init();
    $channels = array();

    // Loop through the URLs, create curl-handles
    // and attach the handles to our multi-request
    foreach ($stationIds as $stationId)
    {
        $soap_request =
            '<?xml version="1.0" encoding="UTF-8"?>
                <SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns6930="http://tempuri.org" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                    <SOAP-ENV:Body>
                        <GetStationById xmlns="http://tempuri.org/">
                            <StationID>' . $stationId . '</StationID>
                            <CityID>5</CityID>
                        </GetStationById>
                    </SOAP-ENV:Body>
                </SOAP-ENV:Envelope>';

        $header = array(
            "Content-type: text/xml;charset=\"utf-8\"",
            "Accept: text/xml",
            "Cache-Control: no-cache",
            "Pragma: no-cache",
            "SOAPAction: \"http://tempuri.org/IBLLStation/GetStationById\"",
            "Content-length: ".strlen($soap_request),
        );


        $ch[$stationId] = curl_init();
        curl_setopt($ch[$stationId], CURLOPT_URL,            $url);
        curl_setopt($ch[$stationId], CURLOPT_RETURNTRANSFER, true );
        curl_setopt($ch[$stationId], CURLOPT_POST,           true );
        curl_setopt($ch[$stationId], CURLOPT_POSTFIELDS,     $soap_request);
        curl_setopt($ch[$stationId], CURLOPT_HTTPHEADER,     $header);
        curl_setopt($ch[$stationId], CURLOPT_FRESH_CONNECT,     TRUE);
        curl_setopt($ch[$stationId], CURLOPT_FORBID_REUSE,     TRUE);

        curl_multi_add_handle($multi, $ch[$stationId]);
    }

    // While we're still active, execute curl
    $active = null;
    do {
        $mrc = curl_multi_exec($multi, $active);
    } while ($mrc == CURLM_CALL_MULTI_PERFORM);

    while ($active && $mrc == CURLM_OK) {
        // Wait for activity on any curl-connection
        if (curl_multi_select($multi) == -1) {
            continue;
        }

        // Continue to exec until curl is ready to
        // give us more data
        do {
            $mrc = curl_multi_exec($multi, $active);
        } while ($mrc == CURLM_CALL_MULTI_PERFORM);
    }

    // Loop through the channels and retrieve the received
    // content, then remove the handle from the multi-handle
    $StationsLastContact = "";
    // echo print_r($channels,TRUE);
    foreach ($ch as $channel) {
        $response = curl_multi_getcontent($channel);
        $startsAt           = strpos($response, "StationLastContact>") + strlen("StationLastContact>");
        $endsAt             = strpos($response, "<", $startsAt);
        $StationLastContact = substr($response, $startsAt, $endsAt - $startsAt);
        $StationLastContact .= "<br />";
        $StationsLastContact .= $StationLastContact;
        curl_multi_remove_handle($multi, $channel);
    }

    // Close the multi-handle and return our results
    curl_multi_close($multi);

    die($StationsLastContact);
Sign up to request clarification or add additional context in comments.

1 Comment

Whoa! I was using a code example from an example that binds multiple URLs and I didn't notice that I was overriding the first item of the channels array. Thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.