socket编程实现简单DNS协议实现获取域名ip(TCP)

来源:互联网 发布:战龙三国魂兵进阶数据 编辑:程序博客网 时间:2024/05/12 11:43

http://www.isayme.org/socket-tcp-dns-ping-ip.html

上次在文章《socket编程实现简单DNS协议实现获取域名ip(UDP)》中提到使用udp协议发送dns数据包查询站点ip,这次带来TCP版本的查询代码。

其实不管是tcp协议还是udp协议,都是构造dns报文,填写查询方式,发送数据包即可。

然而,在dns协议中有个特殊的地方需要重点强调!使用tcp协议和udp协议发送的dns报文有个很容易被忽略的问题:在tcp协议时,除了udp协议时的dns报文数据,还要在原有的报文数据之前添加两个字节,这两个字节指名其后的dns报文数据有多少字节!

除了上述的区别,其他的都一样。

另外,再提个问题,其实在dns服务器返回的数据包中可能包含了同一个域名的多个ip地址,我们在UDP的那篇文章中只解析了最后一个提供的ip地址~,这次的tcp模式同时解析了所有返回的ip地址~

这次的代码使用了文章《socket编程之TCP通信模块》中的头文件。main函数文件代码如下:

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
#include <stdio.h> #include <string.h> #include "tcp_client.h" typedef unsigned short U16; const char srv_ip[] = "8.8.8.8"; #define R_OK    0 #define R_ERROR -1 /*typedef struct _DNS_HDR {       U16 id;     U16 tag;     U16 numq;     U16 numa;     U16 numa1;     U16 numa2; }DNS_HDR;*/ typedef struct { unsigned short id;       // identification number unsigned char rd :1;     // recursion desired unsigned char tc :1;     // truncated message unsigned char aa :1;     // authoritive answer unsigned char opcode :4; // purpose of message unsigned char qr :1;     // query/response flag unsigned char rcode :4;  // response code unsigned char cd :1;     // checking disabled unsigned char ad :1;     // authenticated data unsigned char z :1;      // its z! reserved unsigned char ra :1;     // recursion available unsigned short q_count;  // number of question entries unsigned short ans_count; // number of answer entries unsigned short auth_count; // number of authority entries unsigned short add_count; // number of resource entries }DNS_HDR; /*typedef struct _DNS_QER {     U16 type;     U16 classes; }DNS_QER;*/ typedef struct { unsigned short type; unsigned short classes; }DNS_QES; int main(int argc, char **argv) {     unsigned char buff[1024];     unsigned char *buf = buff + 2;     unsigned char *p;     int len, i;     DNS_HDR  *dnshdr = (DNS_HDR *)buf;     DNS_QES  *dnsqes = NULL;         if (R_ERROR == tcp_client_init(argv[2], 53))     {         printf("Conn Error!\n");         return -1;     }     else     {         printf("Conn OK!\n");     }         memset(buff, 0, 1024);     dnshdr->id = htons(0x2000);//(U16)1;     dnshdr->qr = 0;     dnshdr->opcode = 0;     dnshdr->aa = 0;     dnshdr->tc = 0;     dnshdr->rd = 1;     dnshdr->ra = 1;     dnshdr->z  = 0;     dnshdr->ad = 0;     dnshdr->cd = 0;     dnshdr->rcode = 0;     dnshdr->q_count = htons(1);     dnshdr->ans_count = 0;     dnshdr->auth_count = 0;     dnshdr->add_count = 0;     strcpy(buf + sizeof(DNS_HDR) + 1, argv[1]);     p = buf + sizeof(DNS_HDR) + 1; i = 0;     while (p < (buf + sizeof(DNS_HDR) + 1 + strlen(argv[1])))     {         if ( *p == '.')         {             *(p - i - 1) = i;             i = 0;         }         else         {             i++;         }         p++;     }     *(p - i - 1) = i;                                         dnsqes = (DNS_QES *)(buf + sizeof(DNS_HDR) + 2 + strlen(argv[1]));     dnsqes->classes = htons(1);     dnsqes->type = htons(1);     buff[0] = 0; buff[1] = sizeof(DNS_HDR) + sizeof(DNS_QES) + strlen(argv[1]) + 2;     if (R_ERROR == tcp_client_send(buff, sizeof(DNS_HDR) + sizeof(DNS_QES) + strlen(argv[1]) + 4))     {         printf("Send Error!\n");         return -1;     }     else     {         printf("Send OK!\n");     }         len = tcp_client_recv(buff, 1024);     if (len < 0)     {         printf("Recv Error!\n");         return -1;     }     else     {         printf("Recv OK!\n");     }         if (dnshdr->rcode !=0 || dnshdr->ans_count == 0)     {         printf("Ack Error\n");         return -1;     }     p = buff + 2 + sizeof(DNS_HDR) + sizeof(DNS_QES) + strlen(argv[1]) + 2;     printf("Ans Count = %d\n", ntohs(dnshdr->ans_count));     for (i = 0; i < ntohs(dnshdr->ans_count); i++)     {         p = p + 12;         printf("%s ==> %u.%u.%u.%u\n", argv[1], (unsigned char)*p, (unsigned char)*(p + 1), (unsigned char)*(p + 2), (unsigned char)*(p + 3));         p = p + 4;     }     tcp_client_close();     return 0; }

执行结果如下:

1234567891011121314151617
[root@isayme socket]# ./dns_tcp isayme.org 8.8.8.8 Conn OK! Send OK! Recv OK! Ans Count = 1 isayme.org ==> 173.231.29.114 [root@isayme socket]# ./dns_tcp google.com 8.8.8.8 Conn OK! Send OK! Recv OK! Ans Count = 6 google.com ==> 74.125.71.106 google.com ==> 74.125.71.103 google.com ==> 74.125.71.147 google.com ==> 74.125.71.105 google.com ==> 74.125.71.104 google.com ==> 74.125.71.99

需要的头文件在文章《socket编程之TCP通信模块》中下载!

转载本站文章请注明转载自: 独语者
原创粉丝点击