Chinaunix首页 | 论坛 | 博客
  • 博客访问: 723905
  • 博文数量: 104
  • 博客积分: 4320
  • 博客等级: 上校
  • 技术积分: 1948
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-30 14:42
文章分类

全部博文(104)

文章存档

2012年(4)

2011年(65)

2010年(35)

分类: LINUX

2011-08-13 16:13:13

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <time.h>
  5. #include <netdb.h>
  6. #include <unistd.h>
  7. #include <sys/socket.h>
  8. #include <netinet/in.h>
  9. #include <arpa/inet.h>
  10. #include <errno.h>
  11. #include <signal.h>

  12. #define CATCH_TIME 3600
  13. #define CATCH_IDLE 3600

  14. typedef struct dns_catch dns_catch;
  15. struct dns_catch {
  16.     char* name;
  17.     char addr[16];
  18.     int refresh;
  19.     int access;
  20.     dns_catch* next;
  21. };

  22. static void transmit(int fd, char* buf, size_t count, int toread)
  23. {
  24.     int len, ret;

  25.     for(len=0; len<count; len+=ret) {
  26.         ret = (toread)?(read(fd, buf+len, count-len)):(write(fd, buf+len, count-len));
  27.         if(ret==0 || (ret<0 && errno!=EINTR && errno!=EAGAIN)) {
  28.             perror("daemon transmit:"); exit(-1);
  29.         }
  30.         if(ret<0) ret = 0;
  31.     }
  32. }

  33. static void resolve_request(int sfd, dns_catch** list)
  34. {
  35.     dns_catch *catch;
  36.     int count;
  37.     char head[sizeof(int)*2];
  38.     char *name = NULL, *addr = NULL;

  39.     if(sfd<0 || !list) return;

  40.     transmit(sfd, head, sizeof(int)*2, 1);

  41.     memcpy(&count, head, sizeof(int));
  42.     name = (char*)malloc(count+1);

  43.     transmit(sfd, name, count, 1);

  44.     name[count] = '\0';

  45.     for(catch=*list; catch; catch=catch->next) {
  46.         if(catch->name && !strcmp(catch->name, name)) {
  47.             catch->access = time(NULL);
  48.             addr = catch->addr;
  49.             break;
  50.         }
  51.     }
  52.     if(!addr) {
  53.         struct hostent *he = gethostbyname(name);
  54.         char *p;

  55.         if(he && (p=inet_ntoa(*((struct in_addr*)(he->h_addr)))) && strlen(p)<16) {
  56.             dns_catch *tmp = (dns_catch*)malloc(sizeof(dns_catch));
  57.             memset(tmp, 0, sizeof(dns_catch));

  58.             tmp->name = name;
  59.             strcpy(tmp->addr, p);
  60.             tmp->refresh = time(NULL);
  61.             tmp->access = time(NULL);

  62.             tmp->next = *list;
  63.             *list = tmp;

  64.             name = NULL;
  65.             addr = tmp->addr;
  66.         }
  67.     }
  68.     count = (addr)?(strlen(addr)):(0);
  69.     memcpy(head, &count, sizeof(int));

  70.     transmit(sfd, head, sizeof(int)*2, 0);
  71.     transmit(sfd, addr, count , 0);

  72.     if(name) free(name);
  73. }

  74. static void refresh_list(dns_catch **list)
  75. {
  76.     if(!list) return;

  77.     while(*list) {
  78.         if(time(NULL)-(*list)->access > CATCH_IDLE) {
  79.             dns_catch *catch = *list;
  80.             *list = (*list)->next;
  81.             if(catch->name) free(catch->name);
  82.             free(catch);
  83.             continue;
  84.         }
  85.         if(time(NULL)-(*list)->refresh > CATCH_TIME) {
  86.             struct hostent *he = gethostbyname((*list)->name);
  87.             char *p;

  88.             if(he && (p=inet_ntoa(*((struct in_addr*)(he->h_addr)))) && strlen(p)<16) {
  89.                 strcpy((*list)->addr, p);
  90.                 (*list)->refresh = time(NULL);
  91.             }
  92.         }
  93.         list = &((*list)->next);
  94.     }
  95. }

  96. int main(int args, char* argv[])
  97. {
  98.     int sfd = socket(AF_INET, SOCK_STREAM, 0);
  99.     struct sockaddr_in sa;
  100.     fd_set rset;
  101.     struct timeval tv;
  102.     dns_catch *list = NULL;

  103.     sleep(1);

  104.     sa.sin_family = AF_INET;
  105.     sa.sin_addr.s_addr = htonl(INADDR_ANY);
  106.     sa.sin_port = htons(atoi(argv[1]));
  107.     if(connect(sfd, (struct sockaddr*)&sa, sizeof(sa)) < 0) {
  108.         perror("connect failed:"); exit(-1);
  109.     }
  110.     while(1) {
  111.         FD_ZERO(&rset); FD_SET(sfd, &rset);
  112.         tv.tv_usec = 0; tv.tv_sec = 10;

  113.         if(select(sfd+1, &rset, NULL, NULL, &tv) < 0) {
  114.             perror("select error:"); exit(-1);
  115.         }
  116.         if(FD_ISSET(sfd, &rset)) resolve_request(sfd, &list);

  117.         refresh_list(&list);
  118.     }
  119.     return 0;
  120. }
阅读(806) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~