亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C > 正文

利用stream實現一個簡單的http下載器

2020-01-26 15:08:46
字體:
來源:轉載
供稿:網友

其實這個http下載器的功能已經相當完善了,支持:限速、post投遞和上傳、自定義http header、設置user agent、設置range和超時

而且它還不單純只能下載http,由于使用了stream,所以也支持其他協議,你也可以用它來進行文件之間的copy、純tcp下載等等。。

完整demo請參考:https://github.com/waruqi/tbox/wiki

stream.c

/* ////////////////////////////////////////////////////////////////////////////////////// * includes */#include "../demo.h" /* ////////////////////////////////////////////////////////////////////////////////////// * types */typedef struct __tb_demo_context_t{  // verbose   tb_bool_t      verbose; }tb_demo_context_t; /* ////////////////////////////////////////////////////////////////////////////////////// * func */#ifdef TB_CONFIG_MODULE_HAVE_OBJECTstatic tb_bool_t tb_demo_http_post_func(tb_size_t state, tb_hize_t offset, tb_hong_t size, tb_hize_t save, tb_size_t rate, tb_cpointer_t priv){  // percent  tb_size_t percent = 0;  if (size > 0) percent = (tb_size_t)((offset * 100) / size);  else if (state == TB_STATE_CLOSED) percent = 100;   // trace  tb_trace_i("post: %llu, rate: %lu bytes/s, percent: %lu%%, state: %s", save, rate, percent, tb_state_cstr(state));   // ok  return tb_true;}static tb_bool_t tb_demo_stream_head_func(tb_char_t const* line, tb_cpointer_t priv){  tb_printf("response: %s/n", line);  return tb_true;}static tb_bool_t tb_demo_stream_save_func(tb_size_t state, tb_hize_t offset, tb_hong_t size, tb_hize_t save, tb_size_t rate, tb_cpointer_t priv){  // check  tb_demo_context_t* context = (tb_demo_context_t*)priv;  tb_assert_and_check_return_val(context, tb_false);   // print verbose info  if (context->verbose)   {    // percent    tb_size_t percent = 0;    if (size > 0) percent = (tb_size_t)((offset * 100) / size);    else if (state == TB_STATE_CLOSED) percent = 100;     // trace    tb_printf("save: %llu bytes, rate: %lu bytes/s, percent: %lu%%, state: %s/n", save, rate, percent, tb_state_cstr(state));  }   // ok  return tb_true;} /* ////////////////////////////////////////////////////////////////////////////////////// * globals */static tb_option_item_t g_options[] = {  {'-',  "gzip",     TB_OPTION_MODE_KEY,     TB_OPTION_TYPE_BOOL,    "enable gzip"        },  {'-',  "no-verbose",  TB_OPTION_MODE_KEY,     TB_OPTION_TYPE_BOOL,    "disable verbose info"   },  {'d',  "debug",    TB_OPTION_MODE_KEY,     TB_OPTION_TYPE_BOOL,    "enable debug info"     },  {'k',  "keep-alive",  TB_OPTION_MODE_KEY,     TB_OPTION_TYPE_BOOL,    "keep alive"        },  {'h',  "header",    TB_OPTION_MODE_KEY_VAL,   TB_OPTION_TYPE_CSTR,    "the custem http header"  },  {'-',  "post-data",  TB_OPTION_MODE_KEY_VAL,   TB_OPTION_TYPE_CSTR,    "set the post data"     },  {'-',  "post-file",  TB_OPTION_MODE_KEY_VAL,   TB_OPTION_TYPE_CSTR,    "set the post file"     },  {'-',  "range",    TB_OPTION_MODE_KEY_VAL,   TB_OPTION_TYPE_CSTR,    "set the range"       },  {'-',  "timeout",   TB_OPTION_MODE_KEY_VAL,   TB_OPTION_TYPE_INTEGER,   "set the timeout"      },  {'-',  "limitrate",  TB_OPTION_MODE_KEY_VAL,   TB_OPTION_TYPE_INTEGER,   "set the limitrate"     },  {'h',  "help",     TB_OPTION_MODE_KEY,     TB_OPTION_TYPE_BOOL,    "display this help and exit"},  {'-',  "url",     TB_OPTION_MODE_VAL,     TB_OPTION_TYPE_CSTR,    "the url"          },  {'-',  tb_null,    TB_OPTION_MODE_MORE,    TB_OPTION_TYPE_NONE,    tb_null           } }; /* ////////////////////////////////////////////////////////////////////////////////////// * main */tb_int_t tb_demo_stream_main(tb_int_t argc, tb_char_t** argv){  // done  tb_option_ref_t   option = tb_null;  tb_stream_ref_t   istream = tb_null;  tb_stream_ref_t   ostream = tb_null;  tb_stream_ref_t   pstream = tb_null;  do  {    // init option    option = tb_option_init("stream", "the stream demo", g_options);    tb_assert_and_check_break(option);       // done option    if (tb_option_done(option, argc - 1, &argv[1]))    {      // debug & verbose      tb_bool_t debug = tb_option_find(option, "debug");      tb_bool_t verbose = tb_option_find(option, "no-verbose")? tb_false : tb_true;           // done url      if (tb_option_find(option, "url"))       {        // init istream        istream = tb_stream_init_from_url(tb_option_item_cstr(option, "url"));        tb_assert_and_check_break(istream);           // ctrl http        if (tb_stream_type(istream) == TB_STREAM_TYPE_HTTP)         {          // enable gzip?          if (tb_option_find(option, "gzip"))          {            // auto unzip            if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_AUTO_UNZIP, 1)) break;             // need gzip            if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_HEAD, "Accept-Encoding", "gzip,deflate")) break;          }           // enable debug?          if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_HEAD_FUNC, debug? tb_demo_stream_head_func : tb_null)) break;           // custem header?          if (tb_option_find(option, "header"))          {            // init            tb_string_t key;            tb_string_t val;            tb_string_init(&key);            tb_string_init(&val);             // done            tb_bool_t      k = tb_true;            tb_char_t const*  p = tb_option_item_cstr(option, "header");            while (*p)            {              // is key?              if (k)              {                if (*p != ':' && !tb_isspace(*p)) tb_string_chrcat(&key, *p++);                else if (*p == ':')                 {                  // skip ':'                  p++;                   // skip space                  while (*p && tb_isspace(*p)) p++;                   // is val now                  k = tb_false;                }                else p++;              }              // is val?              else              {                if (*p != ';') tb_string_chrcat(&val, *p++);                else                {                  // skip ';'                  p++;                   // skip space                  while (*p && tb_isspace(*p)) p++;                   // set header                  if (tb_string_size(&key) && tb_string_size(&val))                  {                    if (debug) tb_printf("header: %s: %s/n", tb_string_cstr(&key), tb_string_cstr(&val));                    if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_HEAD, tb_string_cstr(&key), tb_string_cstr(&val))) break;                  }                   // is key now                  k = tb_true;                   // clear key & val                  tb_string_clear(&key);                  tb_string_clear(&val);                }              }            }             // set header            if (tb_string_size(&key) && tb_string_size(&val))            {              if (debug) tb_printf("header: %s: %s/n", tb_string_cstr(&key), tb_string_cstr(&val));              if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_HEAD, tb_string_cstr(&key), tb_string_cstr(&val))) break;            }             // exit             tb_string_exit(&key);            tb_string_exit(&val);          }           // keep alive?          if (tb_option_find(option, "keep-alive"))          {            if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_HEAD, "Connection", "keep-alive")) break;          }           // post-data?          if (tb_option_find(option, "post-data"))          {            tb_char_t const*  post_data = tb_option_item_cstr(option, "post-data");            tb_hize_t      post_size = tb_strlen(post_data);            if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_METHOD, TB_HTTP_METHOD_POST)) break;            if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_POST_DATA, post_data, post_size)) break;            if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_POST_FUNC, tb_demo_http_post_func)) break;            if (debug) tb_printf("post: %llu/n", post_size);          }          // post-file?          else if (tb_option_find(option, "post-file"))          {            tb_char_t const* url = tb_option_item_cstr(option, "post-file");            if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_METHOD, TB_HTTP_METHOD_POST)) break;            if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_POST_URL, url)) break;            if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_POST_FUNC, tb_demo_http_post_func)) break;            if (debug) tb_printf("post: %s/n", url);          }        }         // set range        if (tb_option_find(option, "range"))        {          tb_char_t const* p = tb_option_item_cstr(option, "range");          if (p)          {            // the bof            tb_hize_t eof = 0;            tb_hize_t bof = tb_atoll(p);            while (*p && tb_isdigit(*p)) p++;            if (*p == '-')            {              p++;              eof = tb_atoll(p);            }            if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_RANGE, bof, eof)) break;          }        }         // set timeout        if (tb_option_find(option, "timeout"))        {          tb_size_t timeout = tb_option_item_uint32(option, "timeout");          if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_SET_TIMEOUT, timeout)) break;        }         // print verbose info        if (verbose) tb_printf("open: %s: ../n", tb_option_item_cstr(option, "url"));         // open istream        if (!tb_stream_open(istream))         {          // print verbose info          if (verbose) tb_printf("open: %s/n", tb_state_cstr(tb_stream_state(istream)));          break;        }         // print verbose info        if (verbose) tb_printf("open: ok/n");         // init ostream        if (tb_option_find(option, "more0"))        {          // the path          tb_char_t const* path = tb_option_item_cstr(option, "more0");           // init          ostream = tb_stream_init_from_file(path, TB_FILE_MODE_RW | TB_FILE_MODE_CREAT | TB_FILE_MODE_BINARY | TB_FILE_MODE_TRUNC);           // print verbose info          if (verbose) tb_printf("save: %s/n", path);        }        else        {          // the name          tb_char_t const* name = tb_strrchr(tb_option_item_cstr(option, "url"), '/');          if (!name) name = tb_strrchr(tb_option_item_cstr(option, "url"), '//');          if (!name) name = "/stream.file";           // the path          tb_char_t path[TB_PATH_MAXN] = {0};          if (tb_directory_curt(path, TB_PATH_MAXN))            tb_strcat(path, name);          else break;           // init file          ostream = tb_stream_init_from_file(path, TB_FILE_MODE_RW | TB_FILE_MODE_CREAT | TB_FILE_MODE_BINARY | TB_FILE_MODE_TRUNC);           // print verbose info          if (verbose) tb_printf("save: %s/n", path);        }        tb_assert_and_check_break(ostream);         // the limit rate        tb_size_t limitrate = 0;        if (tb_option_find(option, "limitrate"))          limitrate = tb_option_item_uint32(option, "limitrate");         // save it        tb_hong_t      save = 0;        tb_demo_context_t  context = {0};         context.verbose   = verbose;        if ((save = tb_transfer_done(istream, ostream, limitrate, tb_demo_stream_save_func, &context)) < 0) break;      }      else tb_option_help(option);    }    else tb_option_help(option);   } while (0);   // exit pstream  if (pstream) tb_stream_exit(pstream);  pstream = tb_null;   // exit istream  if (istream) tb_stream_exit(istream);  istream = tb_null;   // exit ostream  if (ostream) tb_stream_exit(ostream);  ostream = tb_null;   // exit option  if (option) tb_option_exit(option);  option = tb_null;   return 0;}#elsetb_int_t tb_demo_stream_main(tb_int_t argc, tb_char_t** argv){  return 0;}#endif

以上所述就是本文的全部內容了,希望大家能夠喜歡。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
蜜臀久久99精品久久久无需会员| 亚洲女同精品视频| 精品美女久久久久久免费| 日韩欧美在线网址| 丰满岳妇乱一区二区三区| 国产欧美日韩高清| 91久久精品国产91久久性色| 国产综合久久久久| 亚洲天堂久久av| 亚洲女人初尝黑人巨大| 国产精品都在这里| 亚洲欧美日韩精品| 亚洲精品网址在线观看| 日韩在线视频免费观看| 欧美理论在线观看| 超碰97人人做人人爱少妇| 日韩在线观看免费| 伦伦影院午夜日韩欧美限制| 91久久在线视频| 国产精品日韩电影| 秋霞成人午夜鲁丝一区二区三区| 97久久超碰福利国产精品…| 日韩欧美国产网站| 亚洲xxxxx电影| 国产精品久久久久久久久久久久| 亚洲国产精品一区二区三区| 韩国欧美亚洲国产| 欧美日韩加勒比精品一区| 亚洲国产欧美一区| 欧美午夜无遮挡| 91麻豆国产精品| 亚洲理论片在线观看| 欧美另类69精品久久久久9999| 亚洲精品久久在线| 九九热这里只有精品6| 国产精品男人的天堂| 日韩中文字幕精品视频| 国产区精品视频| 亚洲黄色成人网| 欧美极品第一页| 日韩av电影免费观看高清| 欧美成人一区二区三区电影| 日韩视频第一页| 亚洲色图狂野欧美| 精品无人区乱码1区2区3区在线| 日本高清+成人网在线观看| 久久伊人精品一区二区三区| 国产午夜精品一区理论片飘花| 国产精品久久97| 亚洲欧美另类中文字幕| 国产成人中文字幕| 日韩av在线网| 国产精品久久久久久久久久久不卡| 欧美大片在线看免费观看| 欧美超级乱淫片喷水| 久久男人av资源网站| 日韩乱码在线视频| 欧美日韩在线第一页| 亚洲午夜女主播在线直播| 55夜色66夜色国产精品视频| 国产精品久久久久福利| 亚洲久久久久久久久久久| 国产精品第8页| 欧美日韩国产精品一区| 日韩精品一区二区视频| 91精品在线观| 波霸ol色综合久久| 日韩激情av在线免费观看| 97超碰色婷婷| 91精品国产九九九久久久亚洲| 国产婷婷97碰碰久久人人蜜臀| 在线成人中文字幕| 亚洲天堂第一页| 国产一区私人高清影院| 91精品国产免费久久久久久| 日韩欧美在线字幕| 欧美日韩在线免费观看| 91po在线观看91精品国产性色| 国产精品一区二区三区在线播放| 国产精品久久久久久久久粉嫩av| 亚洲精品欧美极品| 77777亚洲午夜久久多人| 亚洲国产成人爱av在线播放| 成人免费视频在线观看超级碰| 久久天天躁狠狠躁老女人| 欧美在线一级视频| 久久国产精品久久国产精品| 欧美激情精品久久久久久久变态| 成人深夜直播免费观看| 国产精品一区二区三区久久| 色琪琪综合男人的天堂aⅴ视频| 91免费视频国产| 日韩电影免费在线观看中文字幕| 国产精品草莓在线免费观看| 亚洲欧美日韩久久久久久| 亚洲午夜未删减在线观看| 国产做受69高潮| 欧美一级视频免费在线观看| 尤物yw午夜国产精品视频明星| 一区二区三区高清国产| 亚洲精品一区av在线播放| 91精品国产网站| 91在线中文字幕| 日本一区二区三区四区视频| 欧美一级黄色网| 欧美性生活大片免费观看网址| 成人av资源在线播放| 亚洲一区二区三区四区在线播放| 亚洲精品国产精品国自产在线| 亚洲人成电影网站色…| 热门国产精品亚洲第一区在线| 日韩亚洲欧美中文在线| 久久亚洲私人国产精品va| 51精品在线观看| 欧美影院成年免费版| 亚洲视频在线观看免费| 欧美日韩第一页| 琪琪亚洲精品午夜在线| 亚洲区一区二区| 日韩精品在线免费播放| 欧美精品videossex性护士| 欧美日韩国产区| 亚洲福利视频久久| 日韩69视频在线观看| www.色综合| 欧美日韩中文字幕综合视频| 国产免费久久av| 色诱女教师一区二区三区| 欧美日韩美女在线观看| 欧美激情欧美狂野欧美精品| 91高清视频在线免费观看| 精品成人国产在线观看男人呻吟| 亚洲成人久久久| 青青在线视频一区二区三区| 久久av在线播放| 日韩av在线免费观看一区| 欧美视频二区36p| 91天堂在线观看| 韩国福利视频一区| 97激碰免费视频| 欧美另类在线观看| 欧美一区二区三区免费视| 欧美一级黑人aaaaaaa做受| 日韩av观看网址| 国产精品va在线| 91精品免费视频| 久久精品国产91精品亚洲| 亚洲视频777| 欧美韩国理论所午夜片917电影| 91亚洲国产成人精品性色| 69久久夜色精品国产7777| 欧美成人精品三级在线观看| 欧美一级电影免费在线观看| 欧美专区第一页| 97久久精品在线| 国产精品一区二区久久久久| 欧美性极品少妇精品网站| 国产精品久久久久久一区二区| 国产成人精品久久亚洲高清不卡| 日韩精品一二三四区| 热久久免费视频精品| 中文字幕久久久| 成人性教育视频在线观看| 亚洲另类图片色|