цикл событий libuv и libcurl

#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 для принудительного выполнения цикла навсегда. Затем отправляйте и обрабатывайте все новые запросы в асинхронном обратном вызове.