#c #libcurl
Вопрос:
Я делал небольшой проект, в котором хотел получить запрос на несколько фрагментов данных одновременно, используя libcurl multi. Вот пример
CURL* array[] = { curl_easy_init(), curl_easy_init(), curl_easy_init() }; CURLM* multi = curl_multi_init(); curl_easy_setopt(array[0], CURLOPT_URL, "https://www.example.com/"); curl_easy_setopt(array[1], CURLOPT_URL, "https://www.example.com/"); curl_easy_setopt(array[2], CURLOPT_URL, "https://americas.api.riotgames.com/riot/account/v1/accounts/by-puuid/Dxon1TsoGLOAvUykGYErrEPAT_U9YkQ_jNFZpRxYpfRFwnaYVFULVshNQnZapa4qR_pe5sSBn5MQvw"); for (int i = 0; i lt; 3; i ) { curl_multi_add_handle(multi, array[i]); } int retry = 3; loop: int run = 1; while (run) { CURLMcode mc = curl_multi_perform(multi, amp;run); if (mc == CURLM_OK) { mc = curl_multi_poll(multi, NULL, 0, 0, NULL); } if (mc != CURLM_OK) { // no else because catch both error possibilities exit(0); // error in curl multi } } CURLMsg *msg; long rerun = 0; int msgNum = 0; while (msg = curl_multi_info_read(multi, amp;msgNum)) { if (msg-gt;msg == CURLMSG_DONE) { if (msg-gt;data.result != CURLE_OK) { puts("ERROR"); exit(0); // error with transfer } long httpCode; curl_easy_getinfo(msg-gt;easy_handle, CURLINFO_RESPONSE_CODE, amp;httpCode); if (httpCode == 200) { curl_multi_remove_handle(multi, msg-gt;easy_handle); } else { // error with serverside rerun = httpCode; printf("nError : %dn", rerun); } } else { puts("ERROR"); exit(0); // return num not compelted? } } puts("NExt"); if (rerun amp;amp; --retry) { printf("%d - %dn", retry, rerun); Sleep(1000); goto loop; } puts("Finisheed"); exit(0);
Поэтому сначала я создаю массив простых ручек curl, заполняю всю информацию и помещаю их в curl_multi для выполнения запроса. Код работает нормально, если я установлю все URL-адреса в «https://www.example.com/».
Но в моем случае я запрашиваю с сайта, который может вообще не работать (URL в массиве[2]), поэтому я создал механизм повторных попыток. Если есть HttpCode, который не равен 200, то я повторяю запрос, но только с теми, которые завершились неудачно (я удаляю все простые дескрипторы, которые успешно завершились).
Однако механизм повтора, похоже, повторяет попытку только один раз (когда он должен повторить попытку 3 раза) и, похоже, пропускает остальные. Это результат, который я получаю
...stuff from example.com... Error : 401 NExt 2 - 401 NExt Finisheed
Как вы можете видеть, он повторяет попытку только один раз, а затем останавливается, но, очевидно, произошла ошибка, потому что он не выводит правильный ответ.
Может ли кто-нибудь указать мне правильное направление?
Комментарии:
1. используйте openssl и сокеты
Ответ №1:
curl easy не подлежит повторному запуску, если он хранится в curl multi. Удалите и снова добавьте его. В противном случае вы получите !run
и !msg
на второй итерации.
if (msg-gt;msg == CURLMSG_DONE) { // ... curl_multi_remove_handle(multi, msg-gt;easy_handle); long httpCode; curl_easy_getinfo(msg-gt;easy_handle, CURLINFO_RESPONSE_CODE, amp;httpCode); if (httpCode != 200) { rerun = httpCode; printf("nError : %dn", rerun); curl_multi_add_handle(multi, msg-gt;easy_handle); } // ... }