Curl write callback не вызывается для некоторых дескрипторов - PullRequest
0 голосов
/ 20 апреля 2011

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

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

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

#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, &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(&fdread);
    FD_ZERO(&fdwrite);
    FD_ZERO(&fdexcep);

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

    curl_multi_timeout(multi_handle, &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, &fdread, &fdwrite, &fdexcep, &maxfd);

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

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

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

1 Ответ

0 голосов
/ 26 апреля 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...