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通信模块》中下载!
- socket编程实现简单DNS协议实现获取域名ip(TCP)
- socket编程实现简单DNS协议实现获取域名ip(UDP)
- TCP/IP协议、socket及socket简单实现网络通讯
- 网络编程----------SOCKET编程实现简单的TCP协议
- TCP/IP协议族-----19、域名系统(DNS)
- TCP/IP详解卷1:协议(九)【DNS:域名系统,TFTP:简单文件传送协议】
- TCP/Ip协议+UDP协议+Socket通信的实现
- Socket编程 消息传送 TCP协议(窗口实现) 客户端
- Socket编程 消息传送 TCP协议(窗口实现) 服务器
- 简单的 C++ SOCKET编程 ---基于TCP/IP协议
- 简单的 C++ SOCKET编程 ---基于TCP/IP协议
- 简单的 C++ SOCKET编程 ---基于TCP/IP协议
- 简单的 C++ SOCKET编程 ---基于TCP/IP协议
- 简单的 C++ SOCKET编程 ---基于TCP/IP协议(转)
- 简单的 C++ SOCKET编程 ---基于TCP/IP协议
- 简单的 C++ SOCKET编程 ---基于TCP/IP协议
- 简单的 C++ SOCKET编程 ---基于TCP/IP协议
- 简单的 C++ SOCKET编程 ---基于TCP/IP协议
- hibernate的3种状态
- Socket android&php相关
- Linux 下修改PATH
- Those words and syntax need to be remembered
- 根据hibernate配置文件生成数据库建表脚本
- socket编程实现简单DNS协议实现获取域名ip(TCP)
- Exchange 具有邮件功能的用户和联系人有什么区别
- C++ Lambda 表达式
- 关于《《数据结构与程序设计》》的个人理解(第二章)
- Activitys, Threads, & Memory Leaks
- Android使用XML全攻略(1)
- Android系统手机端抓包方法
- 瀑布流库
- [oracle]初始化参数文件spfile、pfile及修改参数的两种方式