tags:

views:

36

answers:

2

I have an array containing the contents of a MySQL table. I need to put each of these contents into curl_multi_handles so that I can execute them all simultaneously

Here is the code for the array, in case it helps:

$SQL = mysql_query("SELECT url FROM urls") or die(mysql_error()); 
                    while($resultSet = mysql_fetch_array($SQL)){    
                        $urls[]=$resultSet 
                        }

So I need to put be able to send data to each url at the same time. I don't need to get any data back, and in fact I'll be having them time out after two seconds. It only needs to send the data and then close.

My code prior to this, was executing them one at a time. here is that code:

    $SQL = mysql_query("SELECT url FROM shells") or die(mysql_error());                         while($resultSet = mysql_fetch_array($SQL)){                            
            $ch = curl_init($resultSet['url'] . $fullcurl); //load the urls and send GET data
            curl_setopt($ch, CURLOPT_TIMEOUT, 2);           //Only load it for two seconds (Long enough to send the data)
            curl_exec($ch);
            curl_close($ch);

So my question is: How can I load the contents of the array into curl_multi_handle, execute it, and then remove each handle and close the curl_multi_handle?

A: 

You still call curl_init and curl_setopt. Then you load it into a multi_handle, and keep calling execute until it's done. This is based on the documentation at curl_multi_init. Since you're timing out in two seconds, and not processing responses, I think you can just sleep for two seconds at a time. curl_multi_select might be better if you actually need to process the responses.

    $SQL = mysql_query("SELECT url FROM shells") ;
    $mh = curl_multi_init();
    $handles = array();
    while($resultSet = mysql_fetch_array($SQL)){       
            //load the urls and send GET data                     
            $ch = curl_init($resultSet['url'] . $fullcurl); 
            //Only load it for two seconds (Long enough to send the data)
            curl_setopt($ch, CURLOPT_TIMEOUT, 2);           
            curl_multi_add_handle($mh, $ch);
            $handles[] = $ch;
    }

    // Create a status variable so we know when exec is done.
    $running = null;
    //execute the handles
    do {
      // Call exec.  This call is non-blocking, meaning it works in the background.
      curl_multi_exec($mh,$running);
      // Sleep while it's executing.  You could do other work here, if you have any.
      sleep(2);
    // Keep going until it's done.
    } while ($running > 0);

    // For loop to remove (close) the regular handles.
    foreach($handles as $ch)
    {
      // Remove the current array handle.
      curl_multi_remove_handle($mh, $ch);
    } 
    // Close the multi handle
    curl_multi_close($mh);
Matthew Flaschen
Thank you for the response. Can you explain what the code at the bottom does, perhaps using comments? Everything after the first while loop. And curl_multi_add_handle($mh, $ch);, wouldn't that only work for the first one?
Rob
No, you're in a loop, so for every row you create a new handle, set it up, add it to the multi, and add it to our array (which we use later for cleanup).
Matthew Flaschen
Thank you, I'll give it a try shortly, and report back. Soon as I get done mowing the yard, aha.
Rob
Alright, I'm back from mowing the yard, aha. Sorry about that. Would I be able to remove the $running, and the sleep? I don't need to do anything while it runs. It's being accessed via a remote client program. If so, how would this code look without it?
Rob
You still have to somehow know when it's done, which means either using multi_exec and checking when it's done, or using curl_multi_select, which is a different approach.
Matthew Flaschen
I see, so it'd be easiest to do it this way?
Rob
I think so, since all you want to know is "Are they all done?"
Matthew Flaschen
Hm, code caused an error, though I'm not sure what the error is. Just tells me 500 server error. Let me go edit my php.ini
Rob
Aha, worked perfectly. But damn i see a lot of errors...
Rob
A: 

If i were you, i would write class mysql and a class curl. Its very good at all. First i would create a method witch would return all urls from a passed mysql result.

Something like

public function getUrls($mysql_fetch_array)
{
    foreach($mysql_fetch_array as $result)
    {
       $urls[] = $result["url"];
    }                         
}


then you could write a method like curlSend($url,$param)

//remember you have to edit i dont know your full code so its just
// a way you could do it

public function curlSend($url,$param="")
{
$ch = curl_init($resultSet['url'] . $fullcurl); //load the urls and send GET data
            curl_setopt($ch, CURLOPT_TIMEOUT, 2);           //Only load it for two seconds (Long enough to send the data)
            curl_exec($ch);
            curl_close($ch); 

}

public function send()
{
  $urls = getUrls($this->mysql->result($sql));

  foreach($urls as $url)
  {
     $this->curlSend($url);
  }
}

Now this is how you could do it.

streetparade
@Rob sorry i forgot to write that you have to close the curl resource each time you fetch a page.
streetparade
This doesn't address curl_multi at all. It's still single-threaded.
Matthew Flaschen
@Matthew Flaschen, may be you are right maybe not. PHP even doesnt support multi threating. How ever here is a small turorial http://www.somacon.com/p537.php
streetparade