#c #networking #libuv
#c #сеть #libuv
Вопрос:
ниже я вижу пример кода из примера о том, как использовать libuv с libcurl
основная функция выглядит следующим образом:
int main(int argc, char **argv) {
loop = uv_default_loop();
if (argc <= 1)
return 0;
if (curl_global_init(CURL_GLOBAL_ALL)) {
fprintf(stderr, "Could not init cURLn");
return 1;
}
uv_timer_init(loop, amp;timeout);
curl_handle = curl_multi_init();
curl_multi_setopt(curl_handle, CURLMOPT_SOCKETFUNCTION, handle_socket);
curl_multi_setopt(curl_handle, CURLMOPT_TIMERFUNCTION, start_timeout);
while (argc-- > 1) {
add_download(argv[argc], argc);
}
uv_run(loop, UV_RUN_DEFAULT);
curl_multi_cleanup(curl_handle);
return 0;
}
я запутался в том, как начать цикл событий. потому что это выглядит так, когда мы выполняем эту строку
uv_run(loop, UV_RUN_DEFAULT);
в цикле вообще нет ожидающего события, поэтому теоретически цикл не должен завершаться немедленно?
в handle_socket обратного вызова не должно быть изменений для запуска. нет никаких шансов для curl_perform()
запуска, который настроен в обратных вызовах обратных вызовов сокета curl.
что-то не так с моим пониманием?
Комментарии:
1. Существует ожидающее событие, в uv_timer_init добавлен таймер (цикл, amp;timeout); , а также материал, добавленный в handle_socket()
Ответ №1:
uv_timer_init(loop, amp;timeout)
не является ожидающим сокетом, поэтому он не блокирует цикл uv, потому что он не активен (вы можете проверить uv_handle_active) Но curl_multi_add_handle
вызывает функцию обратного вызова с таймаутом ( start_timeout
), и эта функция запускает timeout
таймер, а uv_run вызывает on_timeout
обратный вызов. Вы можете протестировать его, просто переместившись curl_multi_setopt(curl_handle, CURLMOPT_TIMERFUNCTION, start_timeout);
после add_download
цикла, и он перестанет работать.
Ответ №2:
Из документации для uv_run
:
/*
* This function runs the event loop. It will act differently depending on the
* specified mode:
* - UV_RUN_DEFAULT: Runs the event loop until the reference count drops to
* zero. Always returns zero.
* - UV_RUN_ONCE: Poll for new events once. Note that this function blocks if
* there are no pending events. Returns zero when done (no active handles
* or requests left), or non-zero if more events are expected (meaning you
* should run the event loop again sometime in the future).
* - UV_RUN_NOWAIT: Poll for new events once but don't block if there are no
* pending events. Returns zero when done (no active handles
* or requests left), or non-zero if more events are expected (meaning you
* should run the event loop again sometime in the future).
*/
В вашем случае вы вызываете uv_run
с UV_RUN_DEFAULT
, и ваш счетчик ссылок никогда не стремится к нулю. Это означает, что цикл будет фактически блокироваться до тех пор, пока вы не уничтожите все его дескрипторы и ссылки. Однако, если бы вы запустили цикл с UV_RUN_NOWAIT
помощью, функция немедленно вернулась бы.
Ответ №3:
Зарегистрируйте асинхронный наблюдатель. Используется uv_async_init
для принудительного выполнения цикла навсегда. Затем отправляйте и обрабатывайте все новые запросы в асинхронном обратном вызове.