首先,我们简单了解一下 curl_multi_* 系列函数的基本作用:
curl_multi_init():初始化一个多路复用句柄,用于管理多个 cURL 句柄。
curl_multi_add_handle():将一个 cURL 句柄添加到多路复用句柄中。
curl_multi_remove_handle():从多路复用句柄中移除一个 cURL 句柄。
curl_multi_exec():执行所有添加到多路复用句柄中的请求。
curl_multi_close():关闭多路复用句柄并清理资源。
curl_close():关闭一个单独的 cURL 会话句柄,释放与该句柄相关的所有资源。
curl_multi_remove_handle():从多路复用句柄中移除一个 cURL 句柄,但不会直接关闭该 cURL 会话。移除后,该句柄仍然有效,可以在其他地方继续使用或者关闭。
我们需要明确两点:
curl_multi_remove_handle() 是操作多路复用句柄,而不是关闭会话。调用该函数并不会终止请求,也不会释放与该 cURL 会话相关的资源。
curl_close() 会释放资源,当我们调用 curl_close() 时,相关的 cURL 句柄就会被销毁,因此在移除句柄之前,我们并不想销毁它。
根据这些特点,我们来分析调用顺序:
这是推荐的顺序。因为:
当你移除 cURL 句柄时,它会从多路复用句柄中脱离,但并没有关闭这个会话。你可以在之后对该句柄进行其他操作(比如进行日志记录或调试)。
如果你先调用 curl_close(),会话会被直接关闭,无法在之后操作该句柄。
这种顺序是错误的,因为:
一旦调用 curl_close(),cURL 会话会被销毁并释放相关资源。你无法再对已经关闭的句柄进行任何操作,包括从多路复用句柄中移除它。
即使你想从多路复用句柄中移除该会话,cURL 内部可能已经释放了相关资源,导致出现不可预期的错误。
因此,这种顺序可能会导致程序崩溃或未定义的行为。
一个标准的流程应该是:
使用 curl_multi_add_handle() 将每个 cURL 会话添加到多路复用句柄中。
调用 curl_multi_exec() 执行并等待响应。
使用 curl_multi_remove_handle() 从多路复用句柄中移除已完成或不再需要的 cURL 会话。
最后,调用 curl_close() 关闭每个 cURL 会话,并释放相关资源。
调用 curl_multi_close() 关闭多路复用句柄并释放相关资源。
curl_multi_remove_handle() 应该在 curl_close() 之前调用。调用 curl_multi_remove_handle() 只是从多路复用句柄中移除 cURL 会话,而不会释放资源,因此我们可以在移除句柄之后,仍然有机会关闭该 cURL 会话并释放资源。务必避免先调用 curl_close(),否则会导致无法移除句柄的错误。