• linux下http协议 多线程下载实现


    linux下http协议 多线程下载实现

    该程序只能在http协议下工作,等以后研究其他协议时再补充。  : F$ a" M9 u; z& V8 L: ^0 k. {' H
    - d/ f/ @. H% h8 ~. z
    (网络服务器用的是腾讯公司的linuxqq 希望他们能原谅我……)) T6 l: d+ J7 E* ~* G
    编程思路:  ! L0 }7 Q1 `6 ]5 V6 w! V' B3 F
    1、分析http协议 数据包。  % F0 Z9 ~  C' X
    以下是一个请求报文与相应的回复报文的例子  
    " H& w3 B, b  }1 z' _; n; a
    GET /linuxqq/linuxqq-v1.0.2-beta1.i386.rpm HTTP/1.1  ( ~4 J! v# ]0 T6 x( K
    Accept: */*  * t7 h3 \  n7 B- x8 p4 H9 H5 V5 ~, w
    Accept-Language: en-us  2 v, @1 K4 G) Y) r! \0 k
    User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)  - |4 o+ v( Z3 [/ z4 p( D+ a
    Host: :80  
    Connection: Keep-Alive  ) {, q9 Z" I9 C# a
    + j! T: X- ~2 X1 j
    HTTP/1.1 206 Partial Content  
    Content-Length: 1009349  
    Content-Range: bytes 0-1009348/5046743  6 X3 j) p: g# B
    Server: qqdlsrv(1.84 for linux)  6 K$ c6 O  J. s+ S9 C1 q' {! V
    Connection: Keep-alive  
    Content-Disposition: attachment; filename=linuxqq-v1.0.2-beta1.i386.rpm  
    Accept-Ranges: bytes  
    Content-Type: application/octet-stream  ) g: I# q0 [2 d3 f7 n1 {

    2、取得文件大小,然后进行对文件的分块。  
    3、对文件分块下载  
    4、合并文件,并改名。 5 z( e4 l9 [( [& [! C# ^

    总结:这个分块再合并总感觉太过于啰嗦。  / f" J3 f  I0 I5 X
    是否还有另外一种方法,  
    如迅雷,在一开始就取得文件大小就在硬盘分配空间,  
    然后分块下载直接写入到文件的不同块?  1 l2 Z3 t0 h1 p0 F: j
    是否可以用文件指针锁住不同的区域并写入? 
    - U0 Q2 ?/ f2 x$ r- G! d3 C


    /*  4 g8 k: B( ]3 a! U
    * down.c  
    *  6 B, ]( s8 i4 b* }
    *  Created on: Mar 27, 2009  
    *      Author: root  * Q. L) p- O2 P  g. d
    * this program is to download file in http protocol with multthreading  + h' i5 u, F/ m9 g
    */  $ h7 x( R( Z  x* k% u
    #ifndef STRUCT_H_  ! z) n4 w1 o' M; X
    #define STRUCT_H_  
    ; k& ]9 l6 k0 p) ^. w
    #endif /* STRUCT_H_ */  1 z0 D; X8 _) n" v( ~8 X, i% |
    #include <unistd.h>  ; T5 z: U, J5 y: L; f0 x
    #include <stdio.h>  
    #include <stdlib.h>  
    #include <string.h>  6 c7 {3 ^/ A4 R0 A0 M# V( i! S6 j% `
    #include <sys/socket.h>  / `+ I* k7 f5 L. n8 b! \% v
    #include <sys/types.h>  * C% K& m5 P' p/ g4 P
    #include <netdb.h>  8 T9 |: c7 s6 `3 P7 K
    #include <netinet/in.h>  
    //create a struct to save the file part infomation  
    struct filepart  0 I2 c1 y7 {/ l: b* p. ]) u$ a
    {  2 w. q6 H+ l1 K' P; y
    int partnum;  
    char pathname[128];  6 |* R2 \& E  N( a5 K  D
    long int lenth;  
    long int datastar;  - z$ O4 m- ]* e. Y: Q' o* F9 z% Y6 n
    long int dataend;  
    struct filepart *next;  
    };  ; I( o& T/ M+ }# W* f0 `; @5 i
    typedef struct filepart FilePart;  & [. y: U% k* Y+ z; L4 I( |/ ?6 A
    struct hostent *host;  5 ^( y, ^$ {5 T" C
    char filepath[2048];      //save the filepath on the server  
    char hostname[1024];    //save the name of the server  
    char filename[256];       //save the name of the file  9 a. K, t* E  c# ?
    char localpath[512];    
    int port,part;  
    long int FileLen;         //the file lenth  , O- M$ k) ^7 L1 h( V- \
    void getname( char * ulr);   //解析url,并从中取得主机名,ip地址 、文件路径以及端口  
    void filepart( long int datalen,int part );       //对文件进行分块    l" \. h% Y% c$ q7 {! G
    void *getfile( FilePart *pointer);         //下载线程函数  
    long int getFileLen( struct hostent *host  );     //获取http包头,分析文件大小  ' f2 R& i; }  n* b1 ~; Z
    void createthread( FilePart * head, int num );   //创建线程函数 参数为链表头指针和分块数目  
    int mergefile( FilePart * head);  , g& C' ]2 C% `( Q; P9 v( ~
    int main(void)  
    {  0 D# x5 X3 l  I) d1 `  p+ w. N
        char ulr[128];  1 ^- h* k8 ?  M
        printf("please input the website:\n");  
        scanf("%s",ulr);        //数组名
        printf("the website is :%s\n",ulr);  7 p  U$ e$ z4 P; ?, S
        printf("input the direct to save file:\n");  # [( `4 L& V4 P$ }2 y
        scanf("%s",localpath);  
        getname( ulr );             //get the ipaddress of the host  / A$ w; M# U3 c! e  V! S4 A, g
                      // getfile( host );    z- r$ x- R9 h, N: P/ S$ ^6 y
        FileLen = getFileLen( host );     //get the lenth of the file  : a. O& y  b" i& j
        filepart( FileLen, 3);  
    , ~% P* h& M/ |# v( Y1 j
        puts("!!!Hello World!!!"); /* prints !!!Hello World!!! */  - D( ]9 Q, E& ~: e  w
        return EXIT_SUCCESS;  / H2 V7 g% s( s' S) X+ V
    }  # i; x8 n0 i) W& F$ |
    " j  `, M6 }! ~& d! I


    long int getFileLen( struct hostent *host  )  
    {  
        struct sockaddr_in sock_serv;  " T, o$ v7 ?% E3 S4 E, B  v
        int sockfd;  : o6 Q2 u9 I8 r- G. G& }: a
        char Request[1024];  9 ]/ ?- X- ^( _- V9 L/ b. U6 j( M
        long int filelen;  $ ^9 n- o$ C! Z* Y/ _: N* A
        int recvbytes;  
        char *buff ,*buffp,*Plen;  1 ~/ B) ^) h0 C  w) \+ r1 H# q
        buff = (char *)malloc( 1024 * sizeof(char));  1 f$ x/ Z) ^; E' R0 Q1 o2 E/ b  O
        memset( buff, 0, sizeof(buff));  ; o& Z4 G/ p/ ~* f$ ~1 X! s( ]0 b
        sockfd = socket( AF_INET, SOCK_STREAM,0);  
        // printf("sockfd = %d\n",sockfd);  " f9 I. _7 _7 I$ I% G7 L
        if(sockfd < 0)  0 \7 S6 A3 w4 O. E8 m
        {  3 N/ J  o$ F+ Q% I( y
             perror("socket");  3 V4 {- f/ z" \* h- g
             exit(1);  
        }  1 e$ l: v! V+ c. ?) J+ p2 `
        memset( &sock_serv, 0, sizeof( sock_serv));  : ?, c5 o8 W* ?8 P$ ~
        sock_serv.sin_family = AF_INET;  ) p, T; _. A1 P  b) \
        sock_serv.sin_port = htons(port);  
        sock_serv.sin_addr = *((struct in_addr *)host -> h_addr);  : n  H) f! L' W
        if(0>connect(sockfd,(struct sockaddr *)&sock_serv, sizeof(struct sockaddr)))  
        {  
             perror("connect");  ; T& F% G5 o8 S* c
             exit(1);  
        }  1 c  b0 w5 V$ M9 D
        // printf("connect success!\n");  " y, i$ X; s! i# h2 e
        printf("file path is:%s\n",filepath);  ) g9 F7 U* ^! r3 b2 }
        sprintf(Request, "GET %s HTTP/1.1\r\nAccept: */*\r\nAccept-Language: en-us\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows        NT 5.0)\r\nHost: %s:%d\r\nConnection: Keep-Alive\r\n\r\n", filepath, hostname, port);  9 [/ W- H! f# d/ B  A+ ]
        // printf("%s",Request);  
    / g, A5 p  O; g; b" t  f3 E
        //send the http protocl packet  & f/ `, W* e' D8 i) q
        if( 0> send(sockfd, Request, strlen(Request), 0))  
        {  
              perror("send");  
              exit(1);  
        }  
        while( 1 )  0 G' ^0 f" p& ^6 r
        {  $ M1 R9 r0 |0 y8 a
              recvbytes = recv(sockfd, buff, 1024,0);  & g0 Z. K! z+ `
            //  printf("recvbytes = %d",recvbytes);  
              if(0 > recvbytes )  7 w  r. ^6 _7 k7 P" T
              {  
                   perror("recv");  
                   exit(1);  $ W$ y2 _2 J8 N3 b+ ~
              }  
              Plen = strstr(buff, "Length:");  
              if( NULL != Plen )  7 c) m4 C: d4 Q& R; l7 O1 H
              {  
                   Plen = strchr( Plen, ':');  . x. V4 B' q/ l! `$ X. Y$ E) ^  e
                   Plen++;  
                  filelen = atol( Plen );  
                   printf("the file data is %ld\n",filelen);  ' Y% Y5 v/ Q6 Y: x
              }  ; H6 ^% J* N9 B, ^4 A- @% B* |3 j+ l
              buffp = strstr(buff, "\r\n\r\n");  ' v8 P/ f3 X$ d- \' g' ]
              //  printf("\n%s",buff);  % k# @* \- N9 P+ h& V5 v7 m0 Q- B# D
              if( NULL != buffp )  
               break;  3 l4 i* M" r0 P" i" U3 v2 {( {
          }  ; x* y/ l8 n/ _4 B2 w2 [2 E
          free( buff ); buff = NULL;  : [; y# M$ d1 A
          close(sockfd);  5 x. Z- M6 v. V* O
          return filelen;  
    }  4 @7 N' s3 _+ Z6 Z

    void getname( char * ulr)  5 B. M% T+ N9 f8 a, s
    {  0 x+ U8 ^/ u' t3 j7 U' U
      char head[10];          //save the"http://" or "https://"  : k$ W% s) Y* F6 a% C* p1 @/ ]
      char hostname[1024];  
      char *pointer;  , ^9 x& Z4 C& ?8 i
      char *pointer2;  3 Q" P( T4 }8 F& o
      char **addrs;  8 i4 e( z1 q3 Z8 U
      pointer = strstr(ulr,"//");        //move the pointer to the "//" of the url  9 _8 k0 v/ T" w8 X. T
      pointer += 2;                   //move the pointer to the right of "//" of the url  
      strncpy(head, ulr, pointer - ulr);     //copy "  8 I* P% V5 Ohttp://" to head  
                      // printf("head = %s\n",head);  : d0 ?$ [. ^- x: y) M# Z7 Q+ [
      pointer2 = strchr( pointer,':'); //find the port of the server  
      if( pointer2 == NULL)       //if there is no port  1 e' G9 q; g0 eji1即即使ji1   a  a  a plklmkdsd
      {  - G5 K$ q3 ]9 X+ U- V+ \
          char *temp = strchr(pointer,'/');       //move pointer to the first '/'  
          port = 80;  
          if( temp != NULL )  
         {  
             pointer2 = temp++;              //save a pointer pointo the right of the first '/'  6 ]; b6 |+ p3 W7 e  D- d. b
             strncpy(hostname, pointer, pointer2 - pointer);  //save the host name  
             strcpy(filepath, pointer2);            //the right of the first '/' are the filepath and name, then save!  ) b0 U) v) c1 P, F+ I. h6 h! D
             printf("filepath:%s\n",filepath);  : V+ U7 [. Z6 ?# a5 h
             while( NULL != temp )  
               {  
                temp = strchr( temp,'/');            //find the right '/'  # v7 x. D( |, l* c6 w
                if( NULL != temp )  + h- B, c2 G4 o5 t  }% w3 E
                 {  7 j* {- Z# `$ b6 J/ ^
                   pointer2 = temp;  3 `6 D: O# x8 u+ D: [: p2 H
                   temp++;  + b2 A. [8 Q4 s9 r
                   }  $ E' t! j4 [# M! O; H" |
               }  
             strcpy(filename, ++pointer2);           //the right of the right '/' is the file name!  8 k1 I, ~2 b' x8 b
             printf("filename is: %s\n",filename);  0 ]+ p8 r5 b2 f3 R" y; ~+ a
                                    //between the first left '/' and the right '/' is the file path  
             printf("save to %s\n",localpath);  
                                /* if( *temp == 0 )  # A7 ~) o( c" C- f$ X
                                  {  
                                    strcpy(filepath,"/index.html");  
                                    printf("filepath:%s\n",filepath);  
                                  }  1 U- ?9 h! N  b4 ], Y
                                */  5 W+ C0 s" O$ h) W& t
          }  & K3 A; w* _/ A; v, O* L$ A
          else    //if not find the first '/' or temp==NULL
          {  % I; S: m2 e1 J$ J# m0 S
             strcpy(hostname,pointer);  * }( }1 X0 Z2 l
             strcpy(filepath,"/index.html");  2 C$ N, z: v: B6 v) L' P
             printf("filepath = %s\n",filepath);  & R& s3 }  v' J& \% G% z4 b6 T
          }  
      }  ! D' B* H4 R5 z
      else  
        {  4 o* F  O) N5 R8 F
         strncpy(hostname, pointer, pointer2 - pointer);  
         port = atoi(++pointer2);  
         printf("port = %d\n",port);  
        }  % j9 z# ~5 Y4 L& b/ m' B
       printf("hostname = %s\n",hostname);  
       host = gethostbyname(hostname);  ) C. |. L4 U4 u1 g$ A
       // #include <netdb.h
       // struct hostent *gethostbyname(const char * hostname);  
       if( host < 0)  
       {  $ ], k; c. D0 ~- e% i8 {/ L; V
          perror("gethostbyname");  * X1 n# {0 v8 \
          exit(1);  
         }  0 D( v( `% b9 y* e! M( x
      addrs = host -> h_addr_list;     //char **addrs;  8 i4 e( z1 q3 Z8 U
      printf("%s",inet_ntoa(*(struct in_addr *)*addrs));  
      printf("\n");  * _" ?8 [) Q  [6 v* Q; l: j5 Q
    }  
    ! Y9 N$ }7 i: }; b4 |8 \
    void filepart( long int datalen,int part )      //move the file lenth and the number of cutting parts  / k! Q* v; d( D& _/ _) L" k- N
    {  
      long int partlen = datalen / part;  1 j+ z6 J2 h. P) _7 r
      long int end = datalen - 1;  . j( r1 O* ?/ V" m1 o
      int i;  
                        // printf("partlen = %ld\nend = %ld\n",partlen,end);  
      FilePart *head ,*present;  ! n/ s' r( h4 n8 O6 y( s6 G  r* O
      head = (FilePart *)malloc(sizeof(FilePart));    //create the head of the link  
      head -> partnum =  1;  
      head -> datastar = 0;  : h8 `; ^$ W* h; Y/ w+ ?+ E$ b( o
      head -> dataend = partlen;  
      head -> lenth = partlen;  2 V. ~# ]2 V7 l( k
      sprintf(head -> pathname,"%s/part%d",localpath,1);  ( j2 b4 m) B& e1 |2 J
      if(part == 1)  3 E$ i: \' \8 _& A) s- x
        head -> dataend = end;  
        present = head;  9 F$ j. r1 {- r1 N5 v
      for( i = 0; i < part - 1; i++)  ; ]$ G6 Q8 K9 T' z2 B3 K$ ?
      {  8 U, l3 V/ x' Y) M' [2 m6 m# C
        present ->next = (FilePart *)malloc(sizeof(FilePart));  
        memset(present->next, 0, sizeof(FilePart));  4 J( b# m0 v5 c, E" V: a
        present ->next -> partnum = i+2;  
        present ->next -> datastar = present -> dataend +1;  
          if( i == (part-2))    @# a; g: E- S/ q    // judge if it is the last part !
          {  
            present ->next -> dataend = end;  
            present ->next -> lenth = datalen - (part-1)*partlen;  ; O0 m& B6 J6 n" z
           }  + }9 p+ f; r5 R+ \0 S
          else  
           {  1 N) d5 Y; p# S: Q* y$ L. r
            present ->next -> dataend = partlen * (i+2);  % n7 z' n( g+ m0 B/ l7 `" K3 H
            present ->next -> lenth = partlen;  
           }  ' s0 e# ^/ j$ |% d& D6 J
          sprintf(present ->next->pathname,"%s/part%d",localpath,(i+2));  . M% m3 Q& J- A/ Z- H* ?
          present = present->next;  
      }  
      createthread( head, part );  8 F) }  g8 }! D: x" O5 s- l
      mergefile( head );  
    }  & |# G  Q8 |! Z
    void createthread( FilePart * head, int num )  / D0 f" J! y+ m: S4 u+ w
    {  
                    // printf("start to create thread\n");    C1 `% A7 w4 C0 c# u7 Z2 u: l/ B
        int i = 1 ,res;  
        long int pres[num];  * I2 F) s& y7 v" l
        pthread_t thread[num];  
        FilePart *present = head;  ; r9 C" K7 u/ X+ [6 \, `. F
        for(i = 0; i < num; i++)  : S7 L% f  y2 b3 e9 s& Z3 K! U7 q
        {  8 j2 f" v. ]2 A- Z, W4 v& x
          res = pthread_create(&thread, NULL, getfile, present);    S' Y6 A1 h' m- A
          if(res != 0)  * x& n' R4 y$ B6 G& Z
          {  
           perror("thread creation failed");  
           exit(1);  
          }  
         //  printf("start to create thread %d\n",i+1);  
          present = present -> next;  8 ]9 N; C; Z; F6 W/ u6 ~
        }  
        long int all = 0;  9 _7 r& B" e" g  S
        for( i = 0; i < num; i++)  
        {  3 f8 s# g3 p7 @$ m- ~
          res = pthread_join(thread,&pres);  0 W+ o% ]- O9 m) f
         if( res != 0)  
          {  ) e# f' _9 O; I1 o0 u
           perror("pthread join");  
           exit(1);  6 F5 h  L4 r- }) Q/ P
          }  
          printf("thread %d finished!\n",i+1);  1 B1 V! M# T; N$ [% S* B
          all += pres;  3 V0 m5 g+ `* o
        }  . @6 k; y" w, t2 y8 |
        printf("all download:%ld!\n",all);  ! r4 C! w' Q5 S0 f4 w
    }  
    void *getfile( FilePart *pointer)  
    {  
        char buff[1024],request[2048];  
        struct sockaddr_in sock_serv;  8 {9 H- V; }4 U! x9 S
        FILE *fp,* fplog;  / o4 U- V% P) Q* e* N5 {- r
        int recvbytes,psockfd;  : W- o; m; B" L- y9 R
        long int download = 0;  + g: p: n6 b9 Q' c. X
        psockfd = socket(AF_INET, SOCK_STREAM, 0);  
        if( psockfd < 0)  2 y" `! R. M: [7 q/ f0 n
        {  ' M9 A$ l5 f8 w3 F
          perror("socket");  
          pthread_exit(1);  ( X+ Q) s6 ^; W: @& m" q7 e
        }  
        // printf("psockfd = %d\n",psockfd);  
        memset( &sock_serv, 0, sizeof(sock_serv));  
        sock_serv.sin_family = AF_INET;  
        sock_serv.sin_port = htons(port);  
        sock_serv.sin_addr = *((struct in_addr *)host -> h_addr);  + P, Z9 g& @# o7 F2 s
        if( ( connect( psockfd, (struct sockaddr *)&sock_serv, sizeof(struct sockaddr) ) )< 0 )  * ^5 o5 Z7 m3 R* S% W
        {  6 Z" q  E% A" _' D
          perror("connect");  - k: j, l  L% R7 K' @* w
          pthread_exit(1);  6 k3 f' J  _1 K  V
        }  
        // printf("connect success!\n");  
        // printf("filepath is :%s\n",filepath);  
        sprintf(request, "GET %s HTTP/1.1\r\nAccept: */*\r\nAccept-Language: en-us\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows     NT 5.0)\r\nHost: %s:%d\r\nRange:bytes=%d-%d\r\nConnection: Keep-Alive\r\n\r\n",filepath, hostname, port,pointer ->datastar,pointer -     >dataend);  
        // printf("ready to send:\n %s",request);  
        int sends = send( psockfd, request, strlen(request), 0);  - o' o1 P- j5 E# f( Q% b0 d( i
        if( sends < 0)  # D, X0 K% T$ g  W2 a0 l
        {  # u( Y( ~% h8 z9 u* @* Q, p  v  U
          perror("send");  
          exit(1);  1 p) C3 e  @* H/ z
        }  & t; U+ S! w; E' g( C) L! `3 f
        char filelog[32];  
        sprintf(filelog,"/tmp/down/part%dlog",pointer-> partnum);  , Q2 F' T+ F7 }
        fplog = fopen( filelog,"w+");  
        fp = fopen( pointer->pathname,"w+");  
        if(fp < 0 )  * `: G( e2 v0 z- q
        {    U5 o; n( C: a4 E! ?9 q
          perror("open ");  4 Z! b6 O( }6 h( V
          pthread_exit(1);  7 \' _- [$ R( o/ }
        }  
        int  in = 0;  
        do  
        {  
            memset(buff, 0, sizeof(buff));  
            recvbytes = recv(psockfd,buff,1024,0);  
                             //int PASCAL FAR recv( SOCKET s, char FAR* buf, int len, int flags);
                             //s:一个标识已连接套接口的描述字。
                             //buf:用于接收数据的缓冲区
                             //len:缓冲区长度。
                             //flags:指定调用方式。
          //  printf(" recv %d bytes!\n",recvbytes);  & r+ R  ~) ]0 ^% L2 X# R
            if( recvbytes == 0)  : g' Q" u; O4 J7 D( c# k0 Y6 R
               break;  
          //  printf("recvbytes = %d\n",recvbytes);  
            if( recvbytes < 0)  4 S: E, t% Y: [& T# ?6 l; n
            {  
               perror("recv");  
               pthread_exit(1);  
            }  . }6 {# N* Q8 S- a* ~5 ]
            char *p;  4 P2 n& r* e; R* ]4 K+ O
            p = strstr(buff,"\r\n\r\n");  
    8 K6 R% N/ c' V1 E# Y
            /* when recv the file stream,if there don't include http protocol head,skip,or discaerd the head,and save the other to the file */  
            if( !in )  
            {  
                 if(  p != NULL )  
                 {  1 m/ R9 S; g$ t* g! U) |( M
                  p += 4;  5 {( s1 g0 m6 q, r0 f, X
                  in = fwrite(buff, 1, ( p - buff), fplog ); //discard the http protocol head  1 R: b9 ^$ m% G7 Q: H. b/ r
                //    printf("\nin = %d\n (p - buff)=%d\n",in,(p-buff));  
                  recvbytes = recvbytes - ( p - buff );  . Z- y9 [6 l: `( p5 k7 Z$ S# R! t
                //    printf("\n recvbytes = %d\n",recvbytes);  
                  in = fwrite( p, 1, recvbytes, fp);  2 Q5 ?7 W- p$ P( Y0 D- [- O( W
                //    printf("in = %d\n",in);  
                //    printf("%s",buff);  % e* X1 A. ~# y# V
                  download += in;  
                 }  
                 else  
                 {  3 S0 Z' d' j# W; U1 A. V4 j  y
                //    printf("%s",buff);    \- V! F7 @# b& i
                //    fwrite(buff, 1, recvbytes, fp );  ) l' _  V5 |) T3 V# M
                 }  7 c& Y$ G% b0 v- V( [% Y( }. D- W+ p
            }  2 Q( j( j- P% M9 |
           else  
           {  
               in = fwrite(buff,1, recvbytes, fp);  $ s$ K2 E) R; r/ o8 U
              //   printf("in = %d\n",in);  * w5 d! x6 S4 L, q% S
                   download += in;  " f9 s8 P3 x3 i$ _% U5 w
           }  4 m; R( d/ k9 S. Z  _
             //printf("\n");  
        }while( recvbytes > 0 );  
        
        printf("%d have downloaded!\n",download);  . \" Z. g: Y0 n2 A6 w/ w
        fclose(fp);  
        fclose(fplog);  
        close(psockfd);  
        pthread_exit(download);  6 o1 ?4 s8 ^2 f  `) h0 `
    }  ' r4 y! Z% b9 Y
    /*merge all parts to one file and remove the temp file rename the file*/  
    int mergefile( FilePart * head)  1 B9 x- r( K' ?/ J
    {  
        FilePart *present ,*release;  1 A9 X3 m7 {7 {, i
        char *buf = (char *)malloc(1024*sizeof(char));  4 c1 R4 \! Z' p% n" H5 j
        FILE *pfread,*pfwrite;  
        int readnum,writenum;  3 q5 g6 U6 t+ I7 L$ r
        pfwrite = fopen(head->pathname,"ab");  //open the first part as append mode.  
        if( pfwrite < 0)  
        {  
              printf("open file");  
              exit(1);  . S; P( h& b, i) @& I1 h. ], }. b
        }  
        present = head->next;  / a8 N) Q( h0 ?5 L
        while( present )    s: y0 Y3 u% @5 y( k6 ~; c3 f
        {  
              pfread = fopen( present->pathname,"rb");  //open temp part's data  7 }  @& P0 m& I6 h: [+ t- m
             if(pfread < 0)  
              {  : b) X0 I: y$ S  U
                   printf("fopen");  ; r& Q% e* Q4 Y! p4 o! f
                   exit(1);  
              }  
              else  
                   printf("open success!\n");  ( |: H8 p& Y5 ^7 x5 J, u0 j
              while( !feof(pfread))  
              {  
                   readnum = fread( buf, sizeof(char), 1024, pfread); //read data from temp part's  
                   writenum = fwrite( buf, sizeof(char), readnum, pfwrite);  //write to the first part  
                 //   printf("%ld have written!\n",writenum);  
              }  
              printf(" read %d part\n", present->partnum);  
              fclose(pfread);  //close the temp file  
              remove(present->pathname); //remove the temp file which have already read  
              release = present;  ; m' [! |' F! c- Q
              present = present->next;  
              free(release); //release the link  7 d) s& H7 K. O/ N+ `( \
        }  
        free(buf);buf=NULL;  
        fclose(pfwrite);  % `) b% X' m/ ~( w
        sprintf(localpath,"%s/%s",localpath,filename);  
        if( 0 > (rename( head->pathname,localpath)))  
          perror("rename");  
        free(head); //free the head of the link  
        return 0;  0 K: s" }$ `( d- u" [
    }  6 @: e% ^0 p" c/ U/ K* X
    - `0 s, M9 r- J2 T
    运行环境 gcc + linux 2.6  ( }3 Z' B3 }6 q
    [root@Eric home]# ./a.out  
    please input the website:  
    http://dl_dir.qq.com/linuxqq/linuxqq-v1.0.2-beta1.i386.rpm  
    the website is :http://dl_dir.qq.com/linuxqq/linuxqq-v1.0.2-beta1.i386.rpm  : M9 t' _+ i% R% _* E
    input the direct to save file:  ; E  ^* r; |! R  G/ p2 T
    /tmp/down  
    filepath:/linuxqq/linuxqq-v1.0.2-beta1.i386.rpm  
    filename is: linuxqq-v1.0.2-beta1.i386.rpm  # L6 f- q3 O: f4 w6 g+ w( W' Q+ a( c0 d
    save to /tmp/down  
    hostname = dl_dir.qq.com  
    202.104.241.136  
    file path is:/linuxqq/linuxqq-v1.0.2-beta1.i386.rpm  
    the file data is 5046743  $ b% R# z# L1 e- N+ D
    how many parts do you want to download?  ; S$ b/ ]6 _& z- ]7 s
    5  : z1 I0 U+ A7 J. R; y* R
    1009350 have downloaded!  9 {& Z. A2 G5 g. }8 y. d; I
    1009348 have downloaded!  
    1009348 have downloaded!  
    1009349 have downloaded!  5 g$ \6 m9 c' P3 [+ r) a+ s0 I
    thread 1 finished!  
    1009348 have downloaded!  
    thread 2 finished!  5 c- Q- m3 N$ \; d2 C+ S. G
    thread 3 finished!  
    thread 4 finished!  
    thread 5 finished!  " d' A) p* z! p, M! Y
    all download:5046743!  
    open success!  
    read 2 part  
    open success!  
    read 3 part  # a5 a& O2 F( n  C' E
    open success!  
    read 4 part  
    open success!  , f+ s' s  A; F
    read 5 part  
    !!!Hello World!!! ' B, m4 v0 e6 ^: x; J# N

  • 相关阅读:
    页面进度条插件pace.js
    cropper.js头像剪裁
    数组每一项与之前项累加
    css实现波浪纹,水波纹动画
    在echart的map上把symbol替换成gif通过convertToPixel坐标转换成px定位到页面,没有做echart的缩放情况下
    vue折叠面板的收缩动画效果,实现点击按钮展开和收起,并有个高度过渡的动画效果
    vue项目中应用自定义的字体
    vue中监听滚动条事件,通过事件控制其他div滚动,固定表头和列
    好久没写博客了
    在nuxt中使用富文本编辑器quill
  • 原文地址:https://www.cnblogs.com/shenlian/p/2135632.html
Copyright © 2020-2023  润新知