Обратный вызов Curl write не вызывается для некоторых дескрипторов

#curl #callback

#curl #обратный вызов

Вопрос:

Я просто следовал примеру curl multihandle, приведенному в http://curl.haxx.se/libcurl/c/multi-single.html со следующими изменениями:

  1. Я добавил 2 дескриптора к мультиобработке вместо одного.
  2. Я установил параметры CURLOPT_WRITEDATA и CURLOPT_WRITEFUNCTION для обоих дескрипторов.

Предполагается, что ответы должны поступать в функцию обратного вызова write, а не в стандартный вывод. Но когда я запускаю программу, для одного дескриптора curl ответ записывается в стандартный вывод, а для другого вызывается функция обратного вызова write. Если вам интересно, ниже приведена моя полная программа. Я не просто пытаюсь опробовать примеры, я сталкиваюсь с аналогичной проблемой в моем реальном коде (только там хуже, для некоторых дескрипторов curl ответ не отправляется ни на стандартный вывод, ни на обратный вызов), поэтому это важно. Пожалуйста, помогите, пока я не застрелился. Картридж не пуст.

 #include <stdio.h>
#include <string>
#include<iostream>

/* somewhat unix-specific */ 
#include <sys/time.h>
#include <unistd.h>

/* curl stuff */ 
#include <curl/curl.h>
using namespace std;

size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp) //no ordering of responses against requests maintained yet.
{
  cout << "nwrite_data called with non 0 data with userp " << userp;
  cout.flush();
  string* stored_response = (string*)userp;
  string chunk((char*)buffer,nmemb*size/sizeof(char));
  stored_response->append(chunk);
  return nmemb*size;
}


/*
 * Simply download a HTTP file.
 */ 

int main(void)
{
  CURL *http_handle;
  CURLM *multi_handle;

  int still_running; /* keep number of running handles */ 

  http_handle = curl_easy_init();

  string* response = new string("");
  cout << "nresponse pointer for yahoo.com=" << response;
  cout.flush();
  curl_easy_setopt(http_handle, CURLOPT_WRITEDATA, response);
  curl_easy_setopt(http_handle, CURLOPT_WRITEFUNCTION, write_data);

  /* set the options (I left out a few, you'll get the point anyway) */ 
  curl_easy_setopt(http_handle, CURLOPT_URL, "http://www.yahoo.com/");

  /* init a multi stack */ 
  multi_handle = curl_multi_init();

  /* add the individual transfers */ 
  curl_multi_add_handle(multi_handle, http_handle);
  http_handle = curl_easy_init();

  response = new string("");
  cout << "nresponse pointer for google.com=" << response;
  cout.flush();
  // curl_easy_setopt(http_handle, CURLOPT_WRITEDATA, response);
  // curl_easy_setopt(http_handle, CURLOPT_WRITEFUNCTION, write_data);

  /* set the options (I left out a few, you'll get the point anyway) */
  curl_easy_setopt(http_handle, CURLOPT_URL, "http://www.google.com/");
  curl_multi_add_handle(multi_handle, http_handle);

  /* we start some action by calling perform right away */ 
  int multi_perform_ret;
  do
  {
    multi_perform_ret = curl_multi_perform(multi_handle, amp;still_running);
  }
  while(multi_perform_ret == CURLM_CALL_MULTI_PERFORM); 
  while(still_running) {
    cout << "nstill_running=" << still_running;
    cout.flush();
    struct timeval timeout;
    int rc; /* select() return code */ 

    fd_set fdread;
    fd_set fdwrite;
    fd_set fdexcep;
    int maxfd = -1;

    long curl_timeo = -1;

    FD_ZERO(amp;fdread);
    FD_ZERO(amp;fdwrite);
    FD_ZERO(amp;fdexcep);

    /* set a suitable timeout to play around with */ 
    /*
    timeout.tv_sec = 1;
    timeout.tv_usec = 0;

    curl_multi_timeout(multi_handle, amp;curl_timeo);
    if(curl_timeo >= 0) {
      timeout.tv_sec = curl_timeo / 1000;
        if(timeout.tv_sec > 1)
          timeout.tv_sec = 1;
        else
          timeout.tv_usec = (curl_timeo % 1000) * 1000;
    }
    */

    /* get file descriptors from the transfers */ 
    curl_multi_fdset(multi_handle, amp;fdread, amp;fdwrite, amp;fdexcep, amp;maxfd);

    rc = select(maxfd 1, amp;fdread, amp;fdwrite, amp;fdexcep, amp;timeout);

    switch(rc) {
    case -1:
      /* select error */ 
      still_running = 0;
      printf("select() returns error, this is badnessn");
      break;
    case 0:
    default:
      /* timeout or readable/writable sockets */ 
      do
      {
        multi_perform_ret = curl_multi_perform(multi_handle, amp;still_running);
      }
      while(multi_perform_ret == CURLM_CALL_MULTI_PERFORM);
      break;
    }
  }

  curl_multi_cleanup(multi_handle);
  curl_easy_cleanup(http_handle);
  return 0;
}
  

Ответ №1:

Я идиот. Я прокомментировал настройку обратного вызова для 2-го дескриптора curl.