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函数文件代码如下:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | |
#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; | } | |
执行结果如下:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | |
[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通信模块》中下载!
转载本站文章请注明转载自:
独语者