@rg070836rg
2017-01-09T14:51:11.000000Z
字数 6689
阅读 1479
TCP_IP
由于自己的偷懒,现在才开始补作业。
2017年1月9日19点
域名解析协议(DNS)用来把便于人们记忆的主机域名和电子邮件地址映射为计算机易于识别的IP地址。DNS是一种c/s的结构,客户机就是用户用于查找一个名字对应的地址,而服务器通常用于为别人提供查询服务。
本次服务器采用的地址是谷歌的8.8.4.4
主要是利用winsock实现客户端查询。首先介绍几个必要的函数
按照之前的框架,进行winsock的初始化
// 初始化操作bool initWSA(){WSADATA wsaData;int Result = WSAStartup( MAKEWORD( 2, 2 ), &wsaData );if(Result!=0 ){return false;}if( LOBYTE( wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion)!= 2 ){if(WSACleanup()==SOCKET_ERROR)//注释4cout<<"WSACleanup出错<<endl;return false;}return true;}
//创建套接字,根据传来的类型创建,本程序需要创建UDP套接字SOCKET CreateSocket(int type){SOCKET sock=socket(AF_INET,type,0);if (sock == INVALID_SOCKET ){return 0;}return sock;}
typedef struct _DNSHEAD{ //dns 头部USHORT ID;USHORT tag; // dns 标志(参数)USHORT numQ; // 问题数USHORT numA; // 答案数USHORT numA1; // 权威答案数USHORT numA2; // 附加答案数}DnsHead;
typedef struct _DNSQUERY //dns 查询结构{USHORT type;//查询类型,大约有20个不同的类型USHORT classes;//查询类,通常是A类既查询IP地}DnsQuery;
bool SetDNSHead(char *name,char *buf){memset(buf,0,sizeof(DnsHead));//设置头部DnsHead *DnsH = (DnsHead *)buf;DnsH->ID = (USHORT)1;DnsH->tag = htons(0x0100);DnsH->numQ = htons(1);DnsH->numA = 0;DnsQuery *DnsQ =(DnsQuery *) ( buf+ sizeof(DnsHead) );int NameLen = ChName(name,(char *)DnsQ);//设置查询信息DnsQ = (DnsQuery *)( (char *)DnsQ + NameLen );DnsQ->classes = htons(1);DnsQ->type = htons(1);return true;}
int MySendto(SOCKET sockTo, const char FAR * buf,int len,char *addr,USHORT port){if (addr[0]<'0'||addr[0]>'9') //addr 中不是IP 地址,域名解析{struct sockaddr_in addr_in;HOSTENT *host = NULL;host = gethostbyname(addr);//域名解析函数if ( host->h_addr_list[0]!=NULL ){memcpy (&addr_in.sin_addr.s_addr,host->h_addr_list[0], host->h_length);addr = inet_ntoa(addr_in.sin_addr);}}//设置发送数据到的 套接字及地址结构SOCKADDR_IN addrTo;addrTo.sin_addr.S_un.S_addr=inet_addr(addr);addrTo.sin_family=AF_INET;addrTo.sin_port=htons(port);return sendto(sockTo, buf, len, 0,(sockaddr*)&addrTo, sizeof(sockaddr));}
int MyRecvFrom(SOCKET s, char FAR * buf,int len,char *addr,USHORT port){if (addr[0]<'0'||addr[0]>'9') //addr 中不是IP 地址,域名解析{struct sockaddr_in addr_in;HOSTENT *host = NULL;host = gethostbyname(addr);//域名解析函数if ( host->h_addr_list[0]!=NULL ){memcpy ( &addr_in.sin_addr.s_addr,host->h_addr_list[0], host->h_length);addr = inet_ntoa(addr_in.sin_addr);}}//设置发送数据到的 套接字及地址结构SOCKADDR_IN addrFrom;addrFrom.sin_addr.S_un.S_addr=inet_addr(addr);addrFrom.sin_family=AF_INET;addrFrom.sin_port=htons(port);int addrlen = sizeof(SOCKADDR_IN);return recvfrom( s, buf, len, 0, (SOCKADDR *)&addrFrom, &addrlen);}
int main(){int Result=0;char buf[1024]={0};char addr[16] = "8.8.4.4";// dns 服务器地址char *name = NULL; //要查询的域名if ( !initWSA() )//初始化{displayErrWSA("initWSA err!");return 1;}//创建套接字SOCKET sockTo ;if ( (sockTo = CreateSocket(SOCK_DGRAM)) == 0){displayErrWSA("CreatSocket err!");return 1;}while (1){char temp[1024]={0};cout<<"\n请输入要查询的域名:";cin>>temp;if (temp[0] == 'q' ||temp[0] == 'Q'){break;}name = temp;//设置dns 头部SetDNSHead(name,buf);//发送出去的请求数据长度int len = sizeof(DnsHead)+sizeof(DnsQuery)+strlen(name)+2;//发送DNS 请求if ( ( Result =MySendto(sockTo,buf,len,addr,53) ) <= 0){displayErrWSA("sendto err!");continue;}//接收应答if ( (Result =MyRecvFrom(sockTo,buf,1024,addr,53) ) <= 0){displayErrWSA("recvfrom err!");continue;}//简单的取得返回的 IP 地址( 收到的最后4字节 )DnsHead *DnsH = (DnsHead *)buf;if (DnsH->numA == 0){printf("无法解析 %s 的IP 地址。\n",name);continue;}char *getIP =(char *)buf +Result - 4;printf("%s 的IP地址为: ",name);for (int Result= 0 ;Result<4 ;Result++){printf("%u.",(UCHAR )getIP[Result]);}printf("\n");}return 0;}

#include <iostream>#include <Winsock2.h>#include <windows.h>#pragma comment(lib,"ws2_32.lib")using namespace std;typedef struct _DNSHEAD{ //dns 头部USHORT ID;USHORT tag; // dns 标志(参数)USHORT numQ; // 问题数USHORT numA; // 答案数USHORT numA1; // 权威答案数USHORT numA2; // 附加答案数}DnsHead;typedef struct _DNSQUERY //dns 查询结构{USHORT type;//查询类型,大约有20个不同的类型USHORT classes;//查询类,通常是A类既查询IP地}DnsQuery;// 初始化操作bool initWSA(){WSADATA wsaData;int Result = WSAStartup( MAKEWORD( 2, 2 ), &wsaData );if(Result!=0 ){return false;}if( LOBYTE( wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion)!= 2 ){if(WSACleanup()==SOCKET_ERROR)//注释4cout<<"WSACleanup出错\n"<<endl;return false;}return true;}bool SetDNSHead(char *name,char *buf){memset(buf,0,sizeof(DnsHead));//设置头部DnsHead *DnsH = (DnsHead *)buf;DnsH->ID = (USHORT)1;DnsH->tag = htons(0x0100);DnsH->numQ = htons(1);DnsH->numA = 0;DnsQuery *DnsQ =(DnsQuery *) ( buf+ sizeof(DnsHead) );int NameLen = ChName(name,(char *)DnsQ);//设置查询信息DnsQ = (DnsQuery *)( (char *)DnsQ + NameLen );DnsQ->classes = htons(1);DnsQ->type = htons(1);return true;}//显示错误信息void displayErrWSA(char *str){printf("\n%s,err = %d\n",str,WSAGetLastError());getchar();}//域名转化int ChName(char *fname,char *tname){int j =0;int i =strlen(fname)-1;tname[i+2] = 0;int k = i+1;for (; i>=0;i--,k--){if (fname[i] == '.'){tname[k] = j;j=0;}else{tname[k] = fname[i];j++;}}tname[k] = j;return strlen(tname)+1;}//创建套接字SOCKET CreateSocket(int type){SOCKET sock=socket(AF_INET,type,0);if (sock == INVALID_SOCKET ){return 0;}return sock;}//UDP sendtoint MySendto(SOCKET sockTo, const char FAR * buf,int len,char *addr,USHORT port){if (addr[0]<'0'||addr[0]>'9') //addr 中不是IP 地址,域名解析{struct sockaddr_in addr_in;HOSTENT *host = NULL;host = gethostbyname(addr);//域名解析函数if ( host->h_addr_list[0]!=NULL ){memcpy ( &addr_in.sin_addr.s_addr,host->h_addr_list[0], host->h_length);addr = inet_ntoa(addr_in.sin_addr);}}//设置发送数据到的 套接字及地址结构SOCKADDR_IN addrTo;addrTo.sin_addr.S_un.S_addr=inet_addr(addr);addrTo.sin_family=AF_INET;addrTo.sin_port=htons(port);return sendto( sockTo, buf, len, 0,(sockaddr*)&addrTo, sizeof(sockaddr) );}// UDP recvfromint MyRecvFrom(SOCKET s, char FAR * buf,int len,char *addr,USHORT port){if (addr[0]<'0'||addr[0]>'9') //addr 中不是IP 地址,域名解析{struct sockaddr_in addr_in;HOSTENT *host = NULL;host = gethostbyname(addr);//域名解析函数if ( host->h_addr_list[0]!=NULL ){memcpy ( &addr_in.sin_addr.s_addr,host->h_addr_list[0], host->h_length);addr = inet_ntoa(addr_in.sin_addr);}}//设置发送数据到的 套接字及地址结构SOCKADDR_IN addrFrom;addrFrom.sin_addr.S_un.S_addr=inet_addr(addr);addrFrom.sin_family=AF_INET;addrFrom.sin_port=htons(port);int addrlen = sizeof(SOCKADDR_IN);return recvfrom( s, buf, len, 0, (SOCKADDR *)&addrFrom, &addrlen);}int main(){int Result=0;char buf[1024]={0};char addr[16] = "8.8.4.4";// dns 服务器地址char *name = NULL; //要查询的域名if ( !initWSA() )//初始化{displayErrWSA("initWSA err!");return 1;}//创建套接字SOCKET sockTo ;if ( (sockTo = CreateSocket(SOCK_DGRAM)) == 0){displayErrWSA("CreatSocket err!");return 1;}while (1){char temp[1024]={0};cout<<"\n请输入要查询的域名:";cin>>temp;if (temp[0] == 'q' ||temp[0] == 'Q'){break;}name = temp;//设置dns 头部SetDNSHead(name,buf);//发送出去的请求数据长度int len = sizeof(DnsHead)+sizeof(DnsQuery)+strlen(name)+2;//发送DNS 请求if ( ( Result =MySendto(sockTo,buf,len,addr,53) ) <= 0){displayErrWSA("sendto err!");continue;}//接收应答if ( (Result =MyRecvFrom(sockTo,buf,1024,addr,53) ) <= 0){displayErrWSA("recvfrom err!");continue;}//简单的取得返回的 IP 地址( 收到的最后4字节 )DnsHead *DnsH = (DnsHead *)buf;if (DnsH->numA == 0){printf("无法解析 %s 的IP 地址。\n",name);continue;}char *getIP =(char *)buf +Result - 4;printf("%s 的IP地址为: ",name);for (int Result= 0 ;Result<4 ;Result++){printf("%u.",(UCHAR )getIP[Result]);}printf("\n");}return 0;}