⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 http.c

📁 多线程 http资源下载工具 给予linux平台的。还凑合。有bug给我联系
💻 C
📖 第 1 页 / 共 2 页
字号:
	      fprintf (stderr, "alloc memory failure.\n");	      goto __FUNCTION__free_buffer;	    }	}            *(url + MAX_LEN_URL_HTTP + 8) = '\0';      if (-1 == get_redirect_url (buf, url, (MAX_LEN_URL_HTTP + 8)))	{	  fprintf (stderr, "redirect error.\n");	  goto __FUNCTION__close_fd_connect;	}      goto __FUNCTION__redirect;    }  else    {      p = strstr (buf, "\r\n");      *p = '\0';      fprintf (stderr, "%s.\n", buf);    }   __FUNCTION__close_fd_connect:  close (fd_sock); __FUNCTION__free_buffer:  free (buf);  if (0 != redirect)    free (url); __FUNCTION__return:  return retval;}void *recv_response_get_file (void *const args){  int fd_epoll;  struct epoll_event event;    char *buffer_recv;  const size_t size_buffer = 4096;    struct file_range *fr;  ssize_t nbytes_recv;  char *file_name;    int retval = -1;  char *p;  int fd;  int fd_write;  struct command cmd_thread_state;    unsigned int connects_num = (unsigned int) args;    /* create file. */  file_name = base_name (resource.path);  if (-1 == (fd_write = open (file_name, O_CREAT | O_TRUNC | O_WRONLY , 0666)))    {      perror ("Error Create file");      goto __FUNCTION__exit;    }  /* alloc memory for receive data. */  if (NULL == (buffer_recv = calloc (size_buffer, 1)))    {      perror ("Error alloc memory");      goto __FUNCTION__close_fd_write;    }  /* create epoll file descriptor. */  if (-1 == (fd_epoll = epoll_create ((connects_num + 1))))    {      perror ("Error create poll");      goto __FUNCTION__free_buffer_recv;    }  /* setup epoll event. */  if (-1 == epoll_add (fd_epoll, pipe_recv_send[0]))    {      perror ("Error poll file");      goto __FUNCTION__close_fd_epoll;    }  /* ready! */  cmd_thread_state.value = CMD_OK;  send_cmd (&cmd_thread_state);  /* print information of resource. */  print_resource_info ();    /* receive data. */  while (1)    {      if (-1 == epoll_wait_restart (fd_epoll, &event, 1, -1))	{	  perror ("Error poll wait");	  goto __FUNCTION__close_connects;	}            fd = event.data.fd;      /* connection is readable. */      if (pipe_recv_send[0] != fd)	{	  fr = fd_to_file_range (fd);	  if (1 != readable (&event))	    {	      retry (fd_epoll, fr);	      continue;	    }	  	  /* read data. */	  nbytes_recv = recv_restart (fd, (void *)buffer_recv,		\				      (size_buffer - 1), MSG_DONTWAIT);	  if ((-1 == nbytes_recv) || (0 == nbytes_recv))	    {	      if (-1 == nbytes_recv)		retry (fd_epoll, fr);	      continue;	    }        	  /* adjust point to content. */	  if (1 != (*fr).recv)	    {	      if ((0 != strncmp (buffer_recv, RES_RANGE_1_0, LEN_RES_RANGE)) &&\		  (0 != strncmp (buffer_recv, RES_RANGE_1_1, LEN_RES_RANGE)))		{		  fprintf (stderr, "Invalid response.\n");		  goto __FUNCTION__close_connects;		}	      	      *(buffer_recv + nbytes_recv) = '\0';	      if (NULL == (p = strstr (buffer_recv, CONTENT_PFIX)))		continue;	      p += LEN_CONTENT_PFIX;	      nbytes_recv -=(p - buffer_recv);	      (*fr).recv = 1;	    }	  else	    p = buffer_recv;	  /* write. */	  lseek (fd_write, (*fr).offset, SEEK_SET);	  if (-1 == write_restart (fd_write, p, nbytes_recv))	    {	      perror ("Error write file");	      goto __FUNCTION__close_connects;	    }	  	  	  /* update file range. */	  update_file_range (fr, nbytes_recv);	  if (0 == (*fr).nbytes)	    close_connect (fd_epoll, fr);	  /* display result. */	  if (1 == print_result (nbytes_recv))	    {	      retval = 0;	      goto __FUNCTION__close_connects;	    }	}            /* new connection. */      else 	{	  /* readable. */	  if (1 != readable (&event))	    {	      fprintf (stderr, "Error read pipe.\n");	      goto __FUNCTION__close_connects;	    }	  	  /* get fd of new connection. */	  if (NULL == (fr = get_new_connect (fd)))	    goto __FUNCTION__close_connects;	  /* add poll. */	  if (-1 == epoll_add (fd_epoll, (*fr).fd))	    goto __FUNCTION__close_connects;	}    }   __FUNCTION__close_connects:  close_connects (fd_epoll);   __FUNCTION__close_fd_epoll:  close_restart (fd_epoll); __FUNCTION__free_buffer_recv:  free (buffer_recv); __FUNCTION__close_fd_write:  if (0 != retval)    remove (file_name);  else    fsync (fd_write);  close_restart (fd_write);   __FUNCTION__exit:  cmd_thread_state.value = CMD_DONE;  if (-1 == retval)    cmd_thread_state.value = CMD_ERR;    send_cmd (&cmd_thread_state);  return (void *)retval;}int print_result (size_t nbytes_read){  static int count_read = 0;  static size_t nbytes_done = 0;    nbytes_done += nbytes_read;  if (nbytes_done == resource.size)    {      fprintf (stdout, " 100%%\n");      fprintf (stdout, "Success download.\n");      return 1;    }     count_read++;  if (COUNT_READ > count_read)    {      fprintf (stdout, " . ");      fflush (stdout);      fsync (STDOUT_FILENO);      return 0;    }    fprintf (stdout, " %2d%% / ",((nbytes_done * 100) / resource.size));  print_size_human ((resource.size - nbytes_done));  fflush (stdout);  fsync (STDOUT_FILENO);  count_read = 0;  return 0;}void print_size_human (size_t size){  if (size > MB)    fprintf (stdout, "%.1f M\n", ((float) size / MB));  else if (size > KB)    fprintf (stdout, "%.1f K\n", ((float) size / KB));  else    fprintf (stdout, "%u b\n", size);}void print_resource_size (){  fprintf (stdout, "File size: ");  print_size_human (resource.size);}void print_resource_info (){  /* resource name. */  fprintf (stdout, "File name: %s.\n", base_name (resource.path));  print_resource_size ();  }struct file_range *get_new_connect (int fd){  struct file_range *fr = NULL;  while ((-1 == read (fd, &fr, sizeof (struct file_range *))) && (EINTR == errno));  return fr;}inline int readable (struct epoll_event *event){  return (EPOLLIN & (*event).events);}/*  define function for epoll.*/int epoll_add (int fd_epoll, int fd_add){  struct epoll_event event;  int retval;    bzero (&event, sizeof (struct epoll_event));  event.events |= EPOLLIN;  event.data.fd = fd_add;  retval = epoll_ctl (fd_epoll, EPOLL_CTL_ADD, fd_add, &event);  if (-1 == retval)    perror ("Error add poll file");  return retval;}  void epoll_remove (int fd_epoll, int fd_remove){  epoll_ctl (fd_epoll, EPOLL_CTL_DEL, fd_remove, NULL);}/*  define function to operate global struct command `cmd' */void clear_cmd (struct command *const p_cmd){  (*p_cmd).value = 0;  (*p_cmd).opt = NULL;}void wait_cmd (struct command *const p_cmd){  pthread_mutex_lock (&mutex_cmd);  if (0 == cmd.value)    pthread_cond_wait (&cond_cmd_set, &mutex_cmd);  *p_cmd = cmd;  clear_cmd (&cmd);  pthread_cond_signal (&cond_cmd_clear);  pthread_mutex_unlock (&mutex_cmd);}void send_cmd (const struct command *p_cmd){  pthread_mutex_lock (&mutex_cmd);  if (0 != cmd.value)    pthread_cond_wait (&cond_cmd_set, &mutex_cmd);  clear_cmd (&cmd);  cmd = *p_cmd;  pthread_cond_signal (&cond_cmd_set);  pthread_mutex_unlock (&mutex_cmd);}void retry (int fd_epoll, struct file_range *const fr){  struct command cmd_retry;  close_connect (fd_epoll, fr);  cmd_retry.value = CMD_RETRY;  cmd_retry.opt = (void *) fr;  send_cmd (&cmd_retry);} void close_connects (int fd_epoll){  size_t i = 0;  int fd;    while (i < CONNECTS_NUM)    {      fd = (*(files_range + i)).fd;      if (-1 != fd)	close_connect (fd_epoll, (files_range + i));      i++;    }}void close_connect (const int fd_epoll, struct file_range *const fr){  int fd;  fd = (*fr).fd;  epoll_remove (fd_epoll, fd);  close_restart (fd);  clear_file_range (fr);}void clear_file_range (struct file_range *fr){  bzero (fr, sizeof (struct file_range));  (*fr).fd = -1;} void update_file_range (struct file_range *fr, size_t nbytes){  (*fr).offset += nbytes;  (*fr).nbytes -= nbytes;}  struct file_range *fd_to_file_range (int fd){  int i = 0;  struct file_range *fr = NULL;    while (i < CONNECTS_NUM)    {      if (fd == (*(files_range + i)).fd)	fr = (files_range + i);      i++;    }    return fr;}extern void *send_request_get_file (void *const p_file_range){  int fd_sock;  char range[64];  struct file_range *fr;  int sockopt;  size_t last;  struct command cmd_retry;    fr = (struct file_range *) p_file_range;  bzero (range, sizeof (range));  last = (*fr).offset + (*fr).nbytes - 1;  snprintf (range, (sizeof(range) - 1), "Range: bytes=%u-%u\r\n\r\n",	\	    (unsigned int) (*fr).offset, (unsigned int) last);  if (-1 == (fd_sock = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)))    goto __FUNCTION__retry;      if (-1 == connect (fd_sock, (struct sockaddr *) &resource.sockaddr, SIZE_SOCKADDR))    goto __FUNCTION__retry;        if (-1 == send_restart (fd_sock, "GET ", strlen ("GET "), MSG_MORE))    goto __FUNCTION__retry;  if (-1 == send_restart (fd_sock, (void *) resource.path, resource.len_path, MSG_MORE))    goto __FUNCTION__retry;    if (-1 == send_restart (fd_sock, " HTTP/1.0\r\n", strlen (" HTTP/1.0\r\n"), MSG_MORE))    goto __FUNCTION__retry;    if (-1 == send_restart (fd_sock, range, strlen(range), 0))    goto __FUNCTION__retry;  sockopt = 1;  setsockopt (fd_sock, SOL_SOCKET, TCP_NODELAY, (void *) &sockopt, SIZE_INT);    (*fr).recv = 0;  (*fr).fd = fd_sock;  if (-1 == fd_sock)    goto __FUNCTION__retry;  while (-1 == write (pipe_recv_send[1], &fr, sizeof (struct file_range *)))    {      if (EINTR == errno)	continue;      else	goto __FUNCTION__retry;    }    return NULL; __FUNCTION__retry:  cmd_retry.value = CMD_RETRY;  cmd_retry.opt = fr;  send_cmd (&cmd_retry);  return NULL;}size_t c_stolower (char *const s){  size_t len_s;  len_s = strlen (s);  return c_ntolower (s, len_s);}size_t c_ntolower (char *const s, size_t n){  size_t i;    if (NULL == s)    return 0;    i = 0;  do    if ('\0' == c_tolower (s + i))      break;  while (i++ < n);        return i;}char c_tolower (char *const c){  return (C_ISUPPER (*c))? (*c = (*c | 32)): (*c);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -