The transfer is still set in an “easy” handle as described
    above, but with the multi interface you also need a
    multi CURLM * handle created and use that to drive all the individual
    transfers. The multi handle can “hold” one or many easy handles:

    A multi handle can also get certain options set, which you do with
    curl_multi_setopt(), but in the simplest case you might not have anything to
    set there.

    To drive a multi interface transfer, you first need to add all the individual
    easy handles that should be transferred to the multi handle. You can add them
    to the multi handle at any point and you can remove them again whenever you
    like. Removing an easy handle from a multi handle will, of course, remove the
    association and that particular transfer would stop immediately.

    Removing one is just as easily done:

    Having added the easy handles representing the transfers you want to perform,
    you write the transfer loop. With the multi interface, you do the looping so
    you can ask libcurl for a set of file descriptors and a timeout value and do
    the call yourself, or you can use the slightly simplified version
    which does that for us, with curl_multi_wait. The simplest loop would
    basically be this: (note that a real application would check return codes)

    The fourth argument to curl_multi_wait, set to 1000 in the example above, is
    a timeout in milliseconds. It is the longest time the function will wait for
    any activity before it returns anyway. You don’t want to lock up for too long
    before calling again as there are timeouts, progress
    callbacks and more that may loose precision if you do so.

    Both these loops let you use one or more file descriptors of your own on which
    to wait, like if you read from your own sockets or a pipe or similar.

    And again, you can add and remove easy handles to the multi handle at any
    point during the looping. Removing a handle mid-transfer will, of course, abort
    that transfer.

    As the examples above show, a program can detect when an individual transfer
    completes by seeing that the transfers_running variable decreases.

    When you do multiple parallel transfers, more than one transfer can of course
    complete in the same invocation and then you might need
    more than one call to curl_multi_info_read to get info about each completed
    transfer.