这是我参加比赛得到的题目
- 开发一个域名批量查询程序,文本文件data.txt中存储着N个域名,每行一个,
-
要求程序从该文件中读取域名数据,然后获取该域名对应的IP地址列表.比如
-
文件内容为:
-
-
-
-
输出格式为:
-
域名
-
IP个数
-
IP1
-
IP2
-
...
-
例如,上面的例子文件中的输出结果为:
-
-
-
1
-
121.20.3.105
-
-
0
-
-
3
-
212.32.4.211
-
10.52.32.32
-
102.31.0.91
为了加快查询速度我采取了多线程(最大线程数通过参数控制)的方法,下面是我设计的程序流程(以3个线程为例):
下面是我设计保存结果的,由于我用的是多线程,因此用链表保存,这样不会出现线程之间同时修改同一个变量的问题,这样不需要加上锁,只需要把链表指针传入,我设计的链表是一个链表上的各个节点又各自保存另一个链表(保存每个域名的多个ip)
源代码:
- /*
-
* 系统环境:Linux kernel 2.6.18 gcc 4.1.2 pthread,dns服务器使用/etc/resolv.conf的配置
-
* 编译: gcc test1.c -o test1 -lpthread
-
输入参数:
-
参数1:数据文件路径,必须
-
参数2:线程数,不输入则默认为4,最小值为1
-
* 运行: ./test1 datafilename <max thread num> 默认线程数为4
-
* 例子: ./test1 d.txt
-
* 例子: ./test1 d.txt 3
-
* ----------------------------------------------------------------------------------------------------
-
* Copyright (c) 2010 by yifangyou
-
* All rights reserved
-
* ----------------------------------------------------------------------------------------------------
-
* 开发一个域名批量查询程序,文本文件data.txt中存储着N个域名,每行一个,
-
* 要求程序从该文件中读取域名数据,然后获取该域名对应的IP地址列表.比如
-
* 文件内容为:
-
* www.126.com
-
* www.132321321.com
-
* www.baidu.com
-
* 输出格式为:
-
* 域名
-
* IP个数
-
* IP1
-
* IP2
-
* ...
-
* 例如,上面的例子文件中的输出结果为:
-
*
-
* www.126.com
-
* 1
-
* 121.20.3.105
-
* www.132321321.com
-
* 0
-
* www.baidu.com
-
* 3
-
* 212.32.4.211
-
* 10.52.32.32
-
* 102.31.0.91
-
*----------------------------------------------------------------------------------------------------
-
* 本程序的数据结构是
-
* query_list_head
-
* ->query_list1---------------------------->query_list2-------------------->query_list3
-
* ->domain1 ->domain
-
* ip_num1 ip_num
-
* host_list_head host_list_head
-
* ->ip1->ip2->ip3 ->ip2_1->ip2_2->ip2_3
-
*/
-
-
#include <stdio.h> /* for printf */
-
#include <stdlib.h> /* for malloc */
-
#include <string.h> /* for strlen,strdup */
-
#include <errno.h> /* for inet_ntoa */
-
#include <sys/socket.h> /* for inet_ntoa */
-
#include <netinet/in.h> /* for inet_ntoa */
-
#include <arpa/inet.h> /* for inet_ntoa */
-
#include <netdb.h> /* for gethostbyname */
-
#include <pthread.h> /* for pthread_create,pthread_join*/
-
#include <stddef.h> /* for offsetof*/
-
#define MAX_INPUT_LEN 512 /* for max line size */
-
#define MAX_THREAD 4 /* for thread pool maxsize */
-
-
//list head
-
struct llhead {
-
struct llhead *prev, *next;
-
};
-
//list init
-
#define LL_INIT(N) ((N)->next = (N)->prev = (N))
-
-
//get the n node
-
#define LL_ENTRY(P,T,N) ((T *) ((char *) (P) - offsetof(T,N)))
-
-
//append into list,into a queue list
-
#define LL_APPEND(H, N) \
-
do { \
-
((H)->prev)->next = (N); \
-
(N)->prev = ((H)->prev); \
-
(N)->next = (H); \
-
(H)->prev = (N); \
-
} while (0)
-
-
//loop over all elements in a queue
-
#define LL_FOREACH_SAFE(H,N,T) \
-
for (N = (H)->next, T = (N)->next; N != (H); \
-
N = (T), T = (N)->next)
-
/****************************************************************
-
* iplist *
-
****************************************************************/
-
struct host {
-
char *ip;
-
struct llhead host_list;
-
};
-
/****************************************************************
-
* result *
-
****************************************************************/
-
struct query_result{
-
char *domain;
-
int ip_num;
-
struct llhead host_list_head;
-
struct llhead query_list;
-
};
-
-
/****************************************************************
-
* result *
-
****************************************************************/
-
struct query_list{
-
struct llhead query_list_head;
-
};
-
/****************************************************************
-
* add a ip to result's ip list *
-
****************************************************************/
-
struct query_result * addquery(struct query_list * qlist,const char *domain)
-
{
-
struct query_result *qr=NULL;
-
if ((qr = malloc(sizeof(*qr))) != NULL)
-
{
-
qr->domain = strdup(domain);
-
qr->ip_num=0;
-
LL_APPEND(&qlist->query_list_head, &qr->query_list);
-
LL_INIT(&qr->host_list_head);
-
return qr;
-
}else
-
{
-
perror(strerror(errno));
-
return NULL;
-
}
-
}
-
-
/****************************************************************
-
* add a ip to result's ip list *
-
****************************************************************/
-
int addhost(struct query_result * qr,const char *ip)
-
{
-
struct host *hp=NULL;
-
if ((hp = malloc(sizeof(*hp))) != NULL)
-
{
-
hp->ip = strdup(ip);
-
LL_APPEND(&qr->host_list_head, &hp->host_list);
-
return 0;
-
}else
-
{
-
perror(strerror(errno));
-
return -1;
-
}
-
}
-
/****************************************************************
-
* print the result and free ip list *
-
****************************************************************/
-
void printAndFree(struct query_result * qr){
-
struct llhead *lp=NULL, *tmp=NULL;
-
struct host *hp=NULL;
-
printf("%s\n",qr->domain);
-
printf("%d\n",qr->ip_num);
-
LL_FOREACH_SAFE(&qr->host_list_head, lp, tmp)
-
{
-
hp = LL_ENTRY(lp, struct host, host_list);
-
printf("%s\n",hp->ip);
-
free(hp->ip);
-
free(hp);
-
}
-
}
-
-
/****************************************************************
-
* print all result and free all query result *
-
****************************************************************/
-
void printResult(struct query_list * qlist){
-
struct llhead *lp=NULL, *tmp=NULL;
-
struct query_result *qr=NULL;
-
LL_FOREACH_SAFE(&qlist->query_list_head,lp, tmp)
-
{
-
qr = LL_ENTRY(lp, struct query_result, query_list);
-
printAndFree(qr);
-
free(qr->domain);
-
free(qr);
-
}
-
}
-
-
/****************************************************************
-
* resolve the domain get addrlist and record the ip *
-
****************************************************************/
-
int get_ip_list(struct query_result * qr)
-
{
-
if(qr==NULL)
-
{
-
return -1;
-
}
-
int i=0;
-
char *p=NULL;
-
char *domain=qr->domain;
-
struct hostent *h=gethostbyname(domain);
-
if(h==NULL)
-
{
-
perror(strerror(errno));
-
return -1;
-
}
-
while(p=h->h_addr_list[i++])
-
{
-
// printf("domain=%s,ip=%s\n",domain,inet_ntoa(*(struct in_addr*)p));
-
addhost(qr,inet_ntoa(*(struct in_addr*)p));
-
qr->ip_num++;
-
}
-
return 0;
-
}
-
/****************************************************************
-
* read a line from file *
-
****************************************************************/
-
int next_input_line(FILE *fp,char *line, int n) {
-
char *result=NULL;
-
do
-
{
-
result = fgets(line, n, fp);
-
} while ((result != NULL) &&(line[0] == '\n'));
-
-
if (result == NULL)
-
{
-
return (0);
-
}
-
else
-
{
-
return (strlen(line));
-
}
-
}
-
/****************************************************************
-
* remove blank char before str *
-
****************************************************************/
-
char *ltrim(char*p_str)
-
{
-
char *p_tmp=p_str;
-
while(isspace(*p_tmp)!=0)
-
{
-
p_tmp++;
-
}
-
return p_tmp;
-
}
-
/****************************************************************
-
* remove blank char after str *
-
****************************************************************/
-
void rtrim(char*p_str)
-
{
-
char *p_tmp=p_str+strlen(p_str)-1;
-
while(isspace(*p_tmp)!=0)
-
{
-
*p_tmp='\0';
-
p_tmp--;
-
}
-
}
-
/****************************************************************
-
* remove blank char after and before str *
-
****************************************************************/
-
char *trim(char*p_str)
-
{
-
rtrim(p_str);
-
return ltrim(p_str);
-
}
-
-
/****************************************************************
-
* is a number string *
-
****************************************************************/
-
int is_numeric(char*p_str)
-
{
-
while(*p_str)
-
{
-
if(!isdigit(*p_str))
-
{
-
return 0;
-
}
-
p_str++;
-
}
-
return 1;
-
}
-
-
/****************************************************************
-
* main *
-
****************************************************************/
-
int main(int argc,char **argv)
-
{
-
if(argc < 2)
-
{
-
perror("need a filename\n");
-
}
-
//get max thread number
-
int max_thread=MAX_THREAD;
-
if(argc>=3)
-
{
-
if(is_numeric(argv[2]))
-
{
-
max_thread=atoi(argv[2]);
-
if(max_thread<=0)
-
{
-
max_thread=MAX_THREAD;
-
}
-
}
-
}
-
if(max_thread<=0)
-
max_thread=MAX_THREAD;
-
//open data file
-
FILE *fp=NULL;
-
if ((fp = fopen(argv[1], "r")) == NULL) {
-
perror("Error: unable to open datafile\n");
-
return -1;
-
}
-
//init query list
-
struct query_list *qlist=NULL;
-
if((qlist=(struct query_list *)malloc(sizeof(struct query_list)))==NULL)
-
{
-
perror(strerror(errno));
-
if (fclose(fp) != 0)
-
{
-
perror("Error: unable to close datafile\n");
-
return (-1);
-
}
-
return -1;
-
}
-
LL_INIT(&qlist->query_list_head);
-
int j=0;
-
//read file finish flag
-
int got_eof = 0;
-
int thread_i=0;
-
//thread pool
-
pthread_t *pids=(pthread_t *)malloc(max_thread*sizeof(pthread_t));
-
memset(pids,0,max_thread*sizeof(pthread_t));
-
while(got_eof==0)
-
{
-
int input_length = MAX_INPUT_LEN;
-
char input_line[MAX_INPUT_LEN + 1]={0};
-
int len = next_input_line(fp,input_line, input_length);
-
if (len == 0)
-
{
-
//read file finish
-
got_eof = 1;
-
}else
-
{
-
char * domain=trim(input_line);
-
if(strlen(domain)==0)
-
{
-
//skip empty line
-
continue;
-
}
-
struct query_result *qr=addquery(qlist,domain);
-
//multi_thread to resolv the domain
-
if((pthread_create(&pids[thread_i],NULL,(void *) get_ip_list,(void *)qr))!=0)
-
{
-
printf ("Create pthread error!\n");
-
exit (1);
-
}
-
thread_i++;
-
if(thread_i >= max_thread)
-
{
-
for(j=0;j<max_thread;j++)
-
{
-
//waiting for all thread finish
-
if(pids[j]!=0)
-
{
-
pthread_join(pids[j], NULL);
-
pids[j]=0;
-
}
-
}
-
//next loop
-
thread_i=0;
-
}
-
}
-
}
-
//if exists unfinish thread wait
-
for(j=0;j<max_thread;j++)
-
{
-
if(pids[j]!=0)
-
{
-
pthread_join(pids[j], NULL);
-
pids[j]=0;
-
}
-
}
-
free(pids);
-
//output the result
-
printResult(qlist);
-
free(qlist);
-
//close file
-
if (fclose(fp) != 0)
-
{
-
perror("Error: unable to close datafile\n");
-
return (-1);
-
}
-
return 0;
-
}
end
阅读(2167) | 评论(0) | 转发(0) |