@rg070836rg
2017-01-09T22:51:11.000000Z
字数 6689
阅读 1262
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)//注释4
cout<<"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)//注释4
cout<<"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 sendto
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) );
}
// UDP recvfrom
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;
}