Using stream to implement a simple HTTP downloader _c language

Source: Internet
Author: User
Tags keep alive

In fact, this HTTP downloader function has been quite perfect, support: speed limit, post delivery and upload, custom HTTP header, set user agent, set range and timeout

And it is not only download HTTP, because the use of the stream, so also support other protocols, you can also use it to copy between files, pure TCP download and so on.

Full demo Please refer to: 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_object static 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 */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 R
  Ate, 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 */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_c
  STR (state));
}//OK return tb_true; }/*//////////////////////////////////////////////////////////////////////////////////////* Globals/static TB_OP   tion_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 Heade R "}, {'-'," 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_k Ey_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 L Imitrate "}, {' 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_n
 
One, 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 (option, "url") (TB_OPTION_ITEM_CSTR);
   
        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_stre
 
            Am_ctrl_http_set_auto_unzip, 1)) break; Need gzip if (!tb_stream_ctrl (IStream, Tb_stream_ctrl_http_set_head, "accept-encoding", "gzip,deflate") BR
          Eak
          }//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_c
              STR (&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_hea
          D, "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_tconst* 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 = t
          B_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* PA
 
          th = 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, "U
          RL "), '/');
          if (!name) name = TB_STRRCHR (option, "url"), ' \ \ ' (TB_OPTION_ITEM_CSTR);
 
          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; #else tb_int_t Tb_demo_stream_main (tb_int_t argc, tb_char_t** argv) {return 0;} #endif

The above is the entire contents of this article, I hope you can enjoy.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.