24

エラーが発生せず、正常に機能するように、カールハンドルを適切に再利用したいと思います。

私がこのコードを持っているとしましょう:

    CURL *curl;

    curl_global_init(CURL_GLOBAL_ALL);
    curl = curl_easy_init();

    curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/5.0...");
    curl_easy_setopt(curl, CURLOPT_URL, "http://www.google.com");
    curl_easy_perform(curl);

    curl_easy_setopt(curl, CURLOPT_URL, "http://www.bbc.com");
    curl_easy_perform(curl);

    curl_easy_cleanup(curl);
    curl_global_cleanup();

これは、カールハンドルを再利用するための良い方法ですか、それとも正しい方法ですか?curl_easy_reset()または、そのハンドルで使用する必要がありますか?

また、curlで避けるべきことを誰かが提案してくれれば幸いです。誰かが私に既存の情報源へのリンクを教えてくれるかもしれませんか?

4

4 に答える 4

10

curl_easy_perform()私が質問を正しく理解している場合は、電話をかけ、URL のみを変更してから2 回目の電話をかけることができるかどうかを知りたいcurl_easy_setopt()ですか? 関数は以前に設定されたハンドルのオプションを変更しないため、これはエラーなしで機能するはずです。これは短い実用的な例です:

size_t writeCallback(char* contents, size_t size, size_t nmemb, std::string* buffer) {
  size_t realsize = size * nmemb;
  if(buffer == NULL) {
    return 0;
  }
  buffer->append(contents, realsize);
  return realsize;  
}

int main(int argc, char** argv) {
  std::string buffer;

  // Initialize global.
  curl_global_init(CURL_GLOBAL_ALL);

  // Start a libcurl easy session.
  CURL* ch = curl_easy_init();
  if (ch) {
    // Something went wrong
    curl_global_cleanup();
    return -1;
  }

  // These options will only be set once.
  curl_easy_setopt(ch, CURLOPT_VERBOSE, 0);
  curl_easy_setopt(ch, CURLOPT_FOLLOWLOCATION, 1);
  curl_easy_setopt(ch, CURLOPT_USERAGENT, "Crawler");
  curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, &writeCallback);
  curl_easy_setopt(ch, CURLOPT_WRITEDATA, &buffer);

  // Push a couple of URLs onto queue.
  std::vector<const char*> queue;
  queue.push_back("http://www.google.com");
  queue.push_back("http://www.stackoverflow.com");

  const char* url;
  CURLcode code;

  do {
      // Grab an URL from the queue.
      url = queue.back();
      queue.pop_back();

      // Only change the CURLOPT_URL option for the handle
      // the rest will stay intact.
      curl_easy_setopt(ch, CURLOPT_URL, url);

      // Perform transfer.
      code = curl_easy_perform(ch);

      // Check if everything went fine.
      if(code != CURLE_OK) {
        // Handle any errors.
      }

      // Clear the buffer.
      buffer.clear();
  } while(queue.size() > 0);

  // Cleanup.
  curl_easy_cleanup(ch);
  curl_global_cleanup();

  return 0;
}

または、そのハンドルで curl_easy_reset() を使用する必要がありますか?

答えはいいえcurl_easy_perform()です。オプションをリセットしないため、コードは問題なく、curl_easy_setoption(curl, CURLOPT_URL, <newurl>);.

于 2015-02-03T14:18:54.823 に答える
9

簡単なインターフェースで環境 libcurl を使用する場合、最初に以下を呼び出す必要があります。

  • curl_easy_init()、イージー ハンドルを開始します。
  • curl_global_init()、ほとんどの場合、フラグオプションはCURL_GLOBAL_ALL

これら 2 つの関数はそれぞれ、最初に 1 回だけ呼び出され、反対のクリーンアップが必要です。

  • curl_easy_cleanup()宣言したハンドルが終了したら、
  • curl_global_cleanup()libcurl を使い終わったら、

より良い結果を得るには、できる限りエラーをチェックしてください。libcurl はcurl_easy_strerror()そのための機能を提供します。CURLcode エラーを説明する文字列を返します。また、一部の関数は値 CURL_OK を返すか、すべて問題がない場合は特定の整数を返します。

たとえば、 CURLOPT_URL オプションを使用する適切な方法は次のとおりです。

#include <curl.h>

int main(void)
{
    /* declaration of an object CURL */
    CURL *handle;                   

    /* result of the whole process */
    CURLcode result;              

    /* the first functions */
    /* set up the program environment that libcurl needs */
    curl_global_init(CURL_GLOBAL_ALL);
    /* curl_easy_init() returns a CURL easy handle that you're gonna reuse in other easy functions*/
    handle = curl_easy_init();



    /* if everything's all right with the easy handle... */
    if(handle) 
    {
            /* ...you can list the easy functions */
            /* here we just gonna try to get the source code of http://example.com */
            curl_easy_setopt(handle, CURLOPT_URL, "http://example.com");

            /* but in that case we also tell libcurl to follow redirection */
            curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1L);

            /* perform, then store the expected code in 'result'*/ 
            result = curl_easy_perform(handle);

            /* Check for errors */ 
            if(result != CURLE_OK)
            {
                    /* if errors have occured, tell us wath's wrong with 'result'*/
                    fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(result));

                    return 1;
            }
    }
     /* if something's gone wrong with curl at the beginning, we'll appriciate that piece of code */  
    else 
    {
            fprintf(stderr, "Curl init failed!\n");

            return 1;
    }

    /* cleanup since you've used curl_easy_init */ 
    curl_easy_cleanup(handle);

    /* this function releases resources acquired by curl_global_init() */
    curl_global_cleanup();

    /* make the programme stopping for avoiding the console closing befor you can see anything */
    system("PAUSE");

    return 0;
}

そのハンドルをまったく別の目的で再利用したい場合は、別の CURL easy ハンドルを使用することをお勧めします。それでもコードは正常に動作するはずですが、明らかに 2 つの別々の操作であるため、別のハンドルを使用します。

ただし、同じハンドルで作業する必要がある場合があり、自動的にリセットしたくない場合は、適切な関数を使用してください。

void curl_easy_reset(CURL *handle); 

ハンドルからのライブ接続、セッション ID キャッシュ、DNS キャッシュ、Cookie および共有は変更されないことに注意してください。

私はそれを試していませんが、あなたのコードでは次のようなものが得られるはずです:

#include <curl.h>

int main(void)
{
    CURL *handle;                   
    CURLcode result; 

    int error = 0;
    int error2 = 0;             

    curl_global_init(CURL_GLOBAL_ALL);
    handle = curl_easy_init();

    if(handle) 
    {
            curl_easy_setopt(handle, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 6.1; fr; rv:1.9.2) Gecko/20100115 Firefox/3.6");
            curl_easy_setopt(handle, CURLOPT_URL, "http://www.google.com");
            result = curl_easy_perform(handle);

            if(result != CURLE_OK)
            {
                    fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(result));

                    error++;
            }

            Sleep(5000);         // make a pause if you working on console application

            curl_easy_reset(handle);

            curl_easy_setopt(handle, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 6.1; fr; rv:1.9.2) Gecko/20100115 Firefox/3.6");      // have to write it again
            curl_easy_setopt(handle, CURLOPT_URL, "http://www.bbc.com");
            result = curl_easy_perform(handle);

            if(result != CURLE_OK)
            {
                    fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(result));

                    error2++;
            }

            if(error == 1 || error2 == 1)
            {
                    return 1;
            }
    }
    else 
    {
            fprintf(stderr, "Curl init failed!\n");

            return 1;
    }

    curl_easy_cleanup(handle);
    curl_global_cleanup();

    system("PAUSE");

    return 0;
}

に問題がある場合は、5000 を 5 に置き換えるか、5000 を 5Sleepに置き換えてみてください。sleep_sleep

于 2013-02-23T23:51:40.240 に答える
2

または、そのハンドルでcurl_easy_reset()を使用する必要がありますか?

curl_easy_init()Xまたはクリーンアップ(の戻り値を再度割り当てる前)のいずれかをリセットします。両方を実行するのは適切ではありません。詳細については、ドキュメントを参照してください。

于 2013-02-16T14:18:27.390 に答える
0

私は通常、各リクエストの後に自分のカール ハンドルでcurl_easy_resetを呼び出します。これにより、新しいカール ハンドル ( curl_easy_init )を取得することで得られるデフォルト オプションでハンドルを再利用できるため、ハンドルを破棄して要求するサイクルをスキップできます。新しいもの!

于 2021-09-04T09:09:55.377 に答える