c语言winsock 实现简单的域名解析功能(DNS. v 1.0)

 

download

/**************************************
** 实现简单的DNS 学习、测试之用
** VC6.0 winXP 编译通过
** 20100406  v1.0
** from http://blog.csdn.net/jxfgh
************************************/

#include   <stdio.h>
#include   <Winsock2.h>
#include   <windows.h>  

typedef struct _DNSHEAD{   //dns 头部
  USHORT ID;
  USHORT tag;   // dns 标志(参数)
  USHORT numQ;  // 问题数
  USHORT numA;  // 答案数
  USHORT numA1;  // 权威答案数
  USHORT numA2;  // 附加答案数
}DnsHead;
typedef struct _DNSQUERY //dns 查询结构
{
//    char   name[64];
//   //查询的域名,这是一个大小在0到63之间的字符串;
   USHORT type;
   //查询类型,大约有20个不同的类型
   USHORT classes;
   //查询类,通常是A类既查询IP地址。

}DnsQuery;

#pragma comment(lib,"ws2_32.lib")

// 初始化操作
bool initWSA();

//显示错误
void displayErrWSA(char *str);

//创建套接字
SOCKET CreateSocket(int type);

//UDP sendto
int MySendto(SOCKET sockTo, const char FAR * buf,int len,char *addr,USHORT port);

 

// UDP recvfrom
int MyRecvFrom(SOCKET s, char FAR * buf,int len);

//设置DNS 头部
bool SetDNSHead(char *name,char *buf);

int main(int arg,char *are[])
{
 int Result=0;
 char buf[1024]={0};
 char addr[16] = "61.187.72.8";// dns 服务器地址
 char *name = 0; //要查询的域名
 
 if ( !initWSA() )//初始化
 {
  displayErrWSA("initWSA err!");
  return 1;
 }

 //创建套接字
 SOCKET sockTo ;
 if ( (sockTo = CreateSocket(SOCK_DGRAM)) == 0)
 {
  displayErrWSA("CreatSocket err!");
  return 1;
  }
 while (1)
 {
  if (arg < 2)
  {
   char temp[1024]={0};
   printf("/n请输入要查询的域名:");
   scanf("%s",temp);
   if (temp[0] == 'q' ||temp[0] == 'Q')
   {
    break;
   }
   name =  temp;
  }
  else
  {
   arg = 1;
   name =  are[1];
  }

  //设置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) ) <=  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");
 }
 closesocket(sockTo);
 return 0;
}

// 初始化操作
bool initWSA()
{
 WORD   wVersionRequested;
 WSADATA   wsaData;
 int Result;
 wVersionRequested = MAKEWORD( 2, 2 );
 Result = WSAStartup( wVersionRequested, &wsaData );
 if(Result   !=   0 ) 
 {
  return false;
 }
 
 if( LOBYTE( wsaData.wVersion) != 2 ||
    HIBYTE(wsaData.wVersion)!= 2 )
 {
  WSACleanup();
  return false;  
 }
 return true;
}

//*********************************************/
/****************         创建套接字 */
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 recvform*/
int MyRecvFrom(SOCKET s, char FAR * buf,int len)
{

 
 //设置发送数据到的 套接字及地址结构
 SOCKADDR_IN   addrFrom;
 int addrlen = sizeof(SOCKADDR_IN);
 return recvfrom( s, buf, len, 0, (SOCKADDR *)&addrFrom, &addrlen);
}

 

//*********************************************/
/********************** 设置DNS 头部 */
int  ChName(char *fname,char *tname);//域名转化
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;
}

  

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值