1

ここでは、サーバーからファイルをダウンロードするためのコードを実装しました。その正常に動作します。ここで、残り秒数データ1秒あたりのレートなどのデータを計算する独自のプログレスバー関数を作成したいと思います。そこで、ここから、カールプログレスバーオプションを使用する1つの方法を見つけました。このオプションを有効にする方法。私はこれで完全に終わりました。

以下にコードを入れます。このコードでmy_progress_funcは、curlライブラリの時間間隔に従って頻繁に呼び出します。この間隔時間を1秒に変更したいと思います。を使用してcurlライブラリでcurlライブラリのいくつかのオプションを設定することは可能ですか?

my_progress_funcこの関数を1秒ごとに呼び出したい。

コード:

#include <stdio.h>
#include <curl/curl.h>

long test =0;

struct FtpFile {
  const char *filename;
  FILE *stream;
  long iAppend;
};

static size_t my_fwrite(void *buffer, size_t size, size_t nmemb, void *stream)
{
  struct FtpFile *out=(struct FtpFile *)stream;
  if(out && !out->stream) {
    /* open file for writing */
      out->stream=fopen(out->filename, out->iAppend ? "ab":"wb");
    if(!out->stream)
      return -1; /* failure, can't open file to write */
  }
  out->iAppend += nmemb;
  return fwrite(buffer, size, nmemb, out->stream);
}

int my_progress_func(void *bar,
                     double t, /* dltotal */ 
                     double d, /* dlnow */ 
                     double ultotal,
                     double ulnow)
{
    printf("%f : %f \n", d, t);

  return 0;
}

int main(void)
{
  CURL *curl;
  CURLcode res;
  int c;

  struct FtpFile ftpfile={
    "dev.zip", /* name to store the file as if succesful */
    NULL,
  };

  curl_global_init(CURL_GLOBAL_DEFAULT);

  curl = curl_easy_init();
  if(curl) {
    curl_easy_setopt(curl, CURLOPT_URL,
                     "sftp://root:xyz_@192.170.10.1/mnt/xyz.tar");


    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 120L);


    /* Define our callback to get called when there's data to be written */
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
    /* Set a pointer to our struct to pass to the callback */
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile);


    curl_easy_setopt(curl, CURLOPT_FTPPORT, "-");

    /* Switch on full protocol/debug output */

    curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

    curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
    curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, my_progress_func);

    res = curl_easy_perform(curl);

    printf("res is %d\n, data get %ld\n", res, ftpfile.iAppend);


    ///Retry upto 100 times it timeout or connection drop occur
    for (c = 0; (res != CURLE_OK) && (c < 100); c++) {



        curl_easy_setopt(curl, CURLOPT_RESUME_FROM , ftpfile.iAppend);
        res = curl_easy_perform(curl);
        if(res == CURLE_OK) c =0;
        printf("%d res is %d\n, data get %ld\n",c, res, ftpfile.iAppend);

    }
    /* always cleanup */
    curl_easy_cleanup(curl);
  }
  if(ftpfile.stream)
    fclose(ftpfile.stream); /* close the local file */
  curl_global_cleanup();
   return 0;
}
4

1 に答える 1

1

curlのドキュメントによると:http: //curl.haxx.se/libcurl/c/curl_easy_setopt.html

にあるcurl_progress_callbackプロトタイプと一致する必要がある関数ポインタ。この関数は、データが転送されているかどうかに関係なく、操作中に頻繁に(ほぼ1秒に1回以上)間隔を空けて、内部の同等の関数ではなくlibcurlによって呼び出されます。コールバックに渡される不明/未使用の引数値はゼロに設定されます(データのみをダウンロードする場合のように、アップロードサイズは0のままになります)。このコールバックからゼロ以外の値を返すと、libcurlは転送を中止し、CURLE_ABORTED_BY_CALLBACKを返します。

頻繁に呼び出す場合は、time()と静的変数を使用してこれを制限できます。次のようになります。

static time_t prevtime;
time_t currtime;
double dif;
static int first = 1;
if(first) {
    time(&prevtime);
    first = 0;
}
time(&currtime);
dif = difftime(currtime, prevtime);
if(dif < 1.0)
    return;
prevtime = currtime;

明らかに、curlがこの関数をもう1秒間完全に呼び出さない可能性があるというリスクがあります。

于 2012-05-16T08:32:12.770 に答える