code2012

加油,坚持,努力,自信
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

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

Posted on 2011-08-12 00:29  code2012  阅读(2606)  评论(0编辑  收藏  举报

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