本文主要是介绍socket编程实现简单DNS协议实现获取域名ip(TCP),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
上次在文章《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函数文件代码如下:
#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 numberunsigned char rd :1; // recursion desiredunsigned char tc :1; // truncated messageunsigned char aa :1; // authoritive answerunsigned char opcode :4; // purpose of messageunsigned char qr :1; // query/response flagunsigned char rcode :4; // response codeunsigned char cd :1; // checking disabledunsigned char ad :1; // authenticated dataunsigned char z :1; // its z! reservedunsigned char ra :1; // recursion availableunsigned short q_count; // number of question entriesunsigned short ans_count; // number of answer entriesunsigned short auth_count; // number of authority entriesunsigned 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;
}
执行结果如下:
[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通信模块》中下载!
转自:https://blog.csdn.net/bytxl/article/details/10395089
这篇关于socket编程实现简单DNS协议实现获取域名ip(TCP)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!