今天又学习了下winsock的知识,对知识做一下梳理。
1. 域名系统简介:Domain Name System(DNS)
其一个明显的作用是简化人们对IP的记忆方式,比如新浪的域名:www.sina.com,IP地址为“202,108,33,32”。
这IP地址多难记啊。
DNS空间是一个树形结构,树中的节点对应着一个资源集合,每个集合中包含一个或者多个资源记录,描述了与这个
节点名字相关的信息,其他主机可以通过查询操作得到指定资源集合中的具体信息。
1.1 解析器:
对于用户,接触最多的就是解析器,解析器是用户程序与域名服务器之间的接口程序,一般是库函数或系统调用。
当我们在收发邮件或者使用网页时都在使用解析器提供的服务,他把我们输入的名字转换为IP地址。实际上,
我们在地址栏输入“202,108,33,32”也可以访问新浪。
1.2 域名系统模型:
下图显示了应用程序、解析器、和名字服务器之间的典型关系:
主机查询程序 :
#include<stdlib.h>
#include<stdio.h>
#include<winsock2.h>
#pragma comment(lib,"ws2_32") //注入要使用的库文件
int main(int argc ,char *argv[])
{
char *name = NULL,**list_p;
struct hostent *hostent_p;
struct in_addr addr;
WSADATA wsaData;
WSAStartup(MAKEWORD(2,0),&wsaData);//winsock初始化
if(argc == 2) //命令行输入的第二个参数是要解析的主机名或地址
{
name = argv[1];
}
if(name && isdigit(name[0]))//如果name[0]是数字,表示刚才输入的是IP地址
{
addr.s_addr = inet_addr(name);//地址转换函数,在上一篇中有代码实现
if(addr.s_addr == INADDR_NONE)//输入的格式错误
{
printf("[%s] is invaild address\n",name);
return -1;
}
hostent_p = gethostbyaddr((char *)&addr,sizeof(addr),AF_INET);
}
else //输入的不是数字,是字符串,表示输入的是主机名
hostent_p = gethostbyname(name);//得到主机信息
if(hostent_p == NULL)
{
printf("fail to lookup,error:%d\n",WSAGetLastError());
return -1;
}
printf("offical name :%s\n",hostent_p->h_name);//输出主机名称
//如果主机还有别名,输出所有别名
if(*hostent_p->h_aliases)
printf("alias:\n");
for(list_p = hostent_p->h_aliases;*list_p != NULL;list_p++)
{
printf("\t%s\n",*list_p);
}
//根据地址类型(不同的地址类型如IPV4,IPV6,其他类型用unknown表示),将地址打印出来
switch(hostent_p->h_addrtype)
{
case AF_INET:
printf("address type : AF_INET\n");
break;
case AF_INET6:
printf("address type : AF_INET6\n");
break;
default:
printf("address type is unknown\n");
return -1;
}
printf("address:\n");
for(list_p = hostent_p->h_addr_list;*list_p != NULL; list_p++)
{
memcpy(&addr.S_un.S_addr,*list_p,hostent_p->h_length);//从list_p所指的内存地址拷贝hostent_p->h_length长的字节到&addr.S_un.S_addr(地址)
printf("\t%s\n",inet_ntoa(addr));
}
WSACleanup();//释放资源
return 0;
}
运行结果: