Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4174918
  • 博文数量: 291
  • 博客积分: 8003
  • 博客等级: 大校
  • 技术积分: 4275
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-30 18:28
文章分类

全部博文(291)

文章存档

2017年(1)

2013年(47)

2012年(115)

2011年(121)

2010年(7)

分类: C/C++

2011-06-12 21:42:55

这是我参加比赛得到的题目
  1. 开发一个域名批量查询程序,文本文件data.txt中存储着N个域名,每行一个,
  2. 要求程序从该文件中读取域名数据,然后获取该域名对应的IP地址列表.比如
  3. 文件内容为:
  4. 输出格式为:
  5. 域名
  6. IP个数
  7. IP1
  8. IP2
  9. ...
  10. 例如,上面的例子文件中的输出结果为:
  11. 1
  12. 121.20.3.105
  13. 0
  14. 3
  15. 212.32.4.211
  16. 10.52.32.32
  17. 102.31.0.91
为了加快查询速度我采取了多线程(最大线程数通过参数控制)的方法,下面是我设计的程序流程(以3个线程为例):
下面是我设计保存结果的,由于我用的是多线程,因此用链表保存,这样不会出现线程之间同时修改同一个变量的问题,这样不需要加上锁,只需要把链表指针传入,我设计的链表是一个链表上的各个节点又各自保存另一个链表(保存每个域名的多个ip)

源代码:
  1. /*
  2.  * 系统环境:Linux kernel 2.6.18 gcc 4.1.2 pthread,dns服务器使用/etc/resolv.conf的配置
  3.  * 编译: gcc test1.c -o test1 -lpthread
  4.     输入参数:
  5.                参数1:数据文件路径,必须
  6.                参数2:线程数,不输入则默认为4,最小值为1
  7.  * 运行: ./test1 datafilename <max thread num> 默认线程数为4
  8.  * 例子: ./test1 d.txt
  9.  * 例子: ./test1 d.txt 3
  10.  * ----------------------------------------------------------------------------------------------------
  11.  * Copyright (c) 2010 by yifangyou
  12.  * All rights reserved
  13.  * ----------------------------------------------------------------------------------------------------
  14.  * 开发一个域名批量查询程序,文本文件data.txt中存储着N个域名,每行一个,
  15.  * 要求程序从该文件中读取域名数据,然后获取该域名对应的IP地址列表.比如
  16.  * 文件内容为:
  17.  * www.126.com
  18.  * www.132321321.com
  19.  * www.baidu.com
  20.  * 输出格式为:
  21.  * 域名
  22.  * IP个数
  23.  * IP1
  24.  * IP2
  25.  * ...
  26.  * 例如,上面的例子文件中的输出结果为:
  27.  *
  28.  * www.126.com
  29.  * 1
  30.  * 121.20.3.105
  31.  * www.132321321.com
  32.  * 0
  33.  * www.baidu.com
  34.  * 3
  35.  * 212.32.4.211
  36.  * 10.52.32.32
  37.  * 102.31.0.91
  38.  *----------------------------------------------------------------------------------------------------
  39.  * 本程序的数据结构是
  40.  * query_list_head
  41.  * ->query_list1---------------------------->query_list2-------------------->query_list3
  42.  *                      ->domain1 ->domain
  43.  *                      ip_num1 ip_num
  44.  *                      host_list_head host_list_head
  45.  *                      ->ip1->ip2->ip3 ->ip2_1->ip2_2->ip2_3
  46.  */
  47.  
  48. #include <stdio.h> /* for printf */
  49. #include <stdlib.h> /* for malloc */
  50. #include <string.h> /* for strlen,strdup */
  51. #include <errno.h> /* for inet_ntoa */
  52. #include <sys/socket.h> /* for inet_ntoa */
  53. #include <netinet/in.h> /* for inet_ntoa */
  54. #include <arpa/inet.h> /* for inet_ntoa */
  55. #include <netdb.h> /* for gethostbyname */
  56. #include <pthread.h> /* for pthread_create,pthread_join*/
  57. #include <stddef.h> /* for offsetof*/
  58. #define MAX_INPUT_LEN        512 /* for max line size */
  59. #define MAX_THREAD            4 /* for thread pool maxsize */

  60. //list head
  61. struct llhead {
  62.     struct llhead *prev, *next;
  63. };
  64. //list init
  65. #define LL_INIT(N) ((N)->next = (N)->prev = (N))

  66. //get the n node
  67. #define LL_ENTRY(P,T,N) ((T *) ((char *) (P) - offsetof(T,N)))

  68. //append into list,into a queue list
  69. #define LL_APPEND(H, N) \
  70.   do { \
  71.     ((H)->prev)->next = (N); \
  72.     (N)->prev = ((H)->prev); \
  73.     (N)->next = (H); \
  74.     (H)->prev = (N); \
  75.   } while (0)

  76. //loop over all elements in a queue
  77. #define LL_FOREACH_SAFE(H,N,T) \
  78.   for (N = (H)->next, T = (N)->next; N != (H); \
  79.       N = (T), T = (N)->next)
  80. /****************************************************************
  81.  * iplist *
  82.  ****************************************************************/
  83. struct host {
  84.     char *ip;
  85.     struct llhead host_list;
  86. };
  87. /****************************************************************
  88.  * result *
  89.  ****************************************************************/
  90. struct query_result{
  91.     char *domain;
  92.     int ip_num;
  93.     struct llhead host_list_head;
  94.     struct llhead query_list;
  95. };

  96. /****************************************************************
  97.  * result *
  98.  ****************************************************************/
  99. struct query_list{
  100.     struct llhead query_list_head;
  101. };
  102. /****************************************************************
  103.  * add a ip to result's ip list *
  104.  ****************************************************************/
  105. struct query_result * addquery(struct query_list * qlist,const char *domain)
  106. {
  107.     struct query_result *qr=NULL;
  108.     if ((qr = malloc(sizeof(*qr))) != NULL)
  109.     {
  110.         qr->domain = strdup(domain);
  111.         qr->ip_num=0;
  112.         LL_APPEND(&qlist->query_list_head, &qr->query_list);
  113.         LL_INIT(&qr->host_list_head);
  114.         return qr;
  115.     }else
  116.     {
  117.         perror(strerror(errno));
  118.         return NULL;
  119.     }
  120. }

  121. /****************************************************************
  122.  * add a ip to result's ip list *
  123.  ****************************************************************/
  124. int addhost(struct query_result * qr,const char *ip)
  125. {
  126.   struct host *hp=NULL;
  127.   if ((hp = malloc(sizeof(*hp))) != NULL)
  128.   {
  129.       hp->ip = strdup(ip);
  130.       LL_APPEND(&qr->host_list_head, &hp->host_list);
  131.       return 0;
  132.   }else
  133.   {
  134.       perror(strerror(errno));
  135.       return -1;
  136.   }
  137. }
  138. /****************************************************************
  139.  * print the result and free ip list *
  140.  ****************************************************************/
  141. void printAndFree(struct query_result * qr){
  142.     struct llhead *lp=NULL, *tmp=NULL;
  143.     struct host *hp=NULL;
  144.     printf("%s\n",qr->domain);
  145.     printf("%d\n",qr->ip_num);
  146.     LL_FOREACH_SAFE(&qr->host_list_head, lp, tmp)
  147.     {
  148.         hp = LL_ENTRY(lp, struct host, host_list);
  149.         printf("%s\n",hp->ip);
  150.         free(hp->ip);
  151.         free(hp);
  152.     }
  153. }

  154. /****************************************************************
  155.  * print all result and free all query result *
  156.  ****************************************************************/
  157. void printResult(struct query_list * qlist){
  158.      struct llhead *lp=NULL, *tmp=NULL;
  159.     struct query_result *qr=NULL;
  160.     LL_FOREACH_SAFE(&qlist->query_list_head,lp, tmp)
  161.     {
  162.         qr = LL_ENTRY(lp, struct query_result, query_list);
  163.         printAndFree(qr);
  164.         free(qr->domain);
  165.         free(qr);
  166.     }
  167. }

  168. /****************************************************************
  169.  * resolve the domain get addrlist and record the ip *
  170.  ****************************************************************/
  171. int get_ip_list(struct query_result * qr)
  172. {
  173.     if(qr==NULL)
  174.         {
  175.         return -1;    
  176.         }
  177.     int i=0;
  178.     char *p=NULL;
  179.     char *domain=qr->domain;
  180.     struct hostent *h=gethostbyname(domain);
  181.     if(h==NULL)
  182.     {
  183.         perror(strerror(errno));
  184.         return -1;
  185.     }
  186.     while(p=h->h_addr_list[i++])
  187.     {
  188. //     printf("domain=%s,ip=%s\n",domain,inet_ntoa(*(struct in_addr*)p));
  189.         addhost(qr,inet_ntoa(*(struct in_addr*)p));
  190.         qr->ip_num++;
  191.     }
  192.     return 0;
  193. }
  194. /****************************************************************
  195.  * read a line from file *
  196.  ****************************************************************/
  197. int next_input_line(FILE *fp,char *line, int n) {
  198.     char *result=NULL;
  199.     do
  200.     {
  201.         result = fgets(line, n, fp);
  202.     } while ((result != NULL) &&(line[0] == '\n'));

  203.     if (result == NULL)
  204.     {
  205.         return (0);    
  206.     }
  207.     else
  208.         {
  209.         return (strlen(line));
  210.     }
  211. }
  212. /****************************************************************
  213.  * remove blank char before str *
  214.  ****************************************************************/
  215. char *ltrim(char*p_str)
  216. {
  217.     char *p_tmp=p_str;
  218.     while(isspace(*p_tmp)!=0)
  219.     {
  220.         p_tmp++;
  221.     }
  222.     return p_tmp;
  223. }
  224. /****************************************************************
  225.  * remove blank char after str *
  226.  ****************************************************************/
  227. void rtrim(char*p_str)
  228. {
  229.     char *p_tmp=p_str+strlen(p_str)-1;
  230.     while(isspace(*p_tmp)!=0)
  231.     {
  232.         *p_tmp='\0';
  233.         p_tmp--;
  234.     }
  235. }
  236. /****************************************************************
  237.  * remove blank char after and before str *
  238.  ****************************************************************/
  239. char *trim(char*p_str)
  240. {
  241.     rtrim(p_str);
  242.     return ltrim(p_str);
  243. }

  244. /****************************************************************
  245.  * is a number string *
  246.  ****************************************************************/
  247. int is_numeric(char*p_str)
  248. {
  249.     while(*p_str)
  250.     {
  251.         if(!isdigit(*p_str))
  252.         {
  253.             return 0;    
  254.         }
  255.         p_str++;
  256.     }
  257.     return 1;
  258. }

  259. /****************************************************************
  260.  * main *
  261.  ****************************************************************/
  262. int main(int argc,char **argv)
  263. {
  264.     if(argc < 2)
  265.     {
  266.         perror("need a filename\n");
  267.     }
  268.     //get max thread number
  269.     int max_thread=MAX_THREAD;
  270.     if(argc>=3)
  271.     {
  272.         if(is_numeric(argv[2]))
  273.         {
  274.             max_thread=atoi(argv[2]);
  275.             if(max_thread<=0)
  276.             {
  277.                 max_thread=MAX_THREAD;
  278.             }
  279.         }
  280.     }
  281.     if(max_thread<=0)
  282.         max_thread=MAX_THREAD;
  283.     //open data file
  284.     FILE *fp=NULL;
  285.     if ((fp = fopen(argv[1], "r")) == NULL) {
  286.         perror("Error: unable to open datafile\n");
  287.         return -1;
  288.     }
  289.     //init query list
  290.     struct query_list *qlist=NULL;
  291.     if((qlist=(struct query_list *)malloc(sizeof(struct query_list)))==NULL)
  292.     {
  293.         perror(strerror(errno));
  294.         if (fclose(fp) != 0)
  295.         {
  296.             perror("Error: unable to close datafile\n");
  297.             return (-1);
  298.         }
  299.         return -1;
  300.     }
  301.     LL_INIT(&qlist->query_list_head);
  302.     int j=0;
  303.     //read file finish flag
  304.     int got_eof = 0;
  305.     int thread_i=0;
  306.     //thread pool
  307.     pthread_t *pids=(pthread_t *)malloc(max_thread*sizeof(pthread_t));
  308.     memset(pids,0,max_thread*sizeof(pthread_t));
  309.     while(got_eof==0)
  310.     {
  311.         int input_length = MAX_INPUT_LEN;
  312.         char input_line[MAX_INPUT_LEN + 1]={0};
  313.         int len = next_input_line(fp,input_line, input_length);
  314.         if (len == 0)
  315.         {
  316.             //read file finish
  317.             got_eof = 1;
  318.                 }else
  319.                 {
  320.             char * domain=trim(input_line);
  321.             if(strlen(domain)==0)
  322.             {
  323.                  //skip empty line
  324.                 continue;
  325.             }
  326.             struct query_result *qr=addquery(qlist,domain);
  327.             //multi_thread to resolv the domain
  328.             if((pthread_create(&pids[thread_i],NULL,(void *) get_ip_list,(void *)qr))!=0)
  329.             {
  330.                 printf ("Create pthread error!\n");
  331.                 exit (1);
  332.             }
  333.             thread_i++;
  334.             if(thread_i >= max_thread)
  335.             {
  336.                 for(j=0;j<max_thread;j++)
  337.                 {
  338.                     //waiting for all thread finish
  339.                     if(pids[j]!=0)
  340.                     {
  341.                         pthread_join(pids[j], NULL);
  342.                         pids[j]=0;
  343.                     }        
  344.                 }
  345.                 //next loop
  346.                 thread_i=0;
  347.             }
  348.         }    
  349.     }
  350.     //if exists unfinish thread wait
  351.     for(j=0;j<max_thread;j++)
  352.     {
  353.         if(pids[j]!=0)
  354.         {
  355.             pthread_join(pids[j], NULL);    
  356.             pids[j]=0;        
  357.         }
  358.     }
  359.     free(pids);
  360.     //output the result
  361.     printResult(qlist);
  362.     free(qlist);
  363.       //close file
  364.     if (fclose(fp) != 0)
  365.     {
  366.         perror("Error: unable to close datafile\n");
  367.         return (-1);
  368.     }
  369.     return 0;
  370. }
end
阅读(2123) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~