查询主机名对应的IP地址
操作步骤:
- 编译:gcc getip.c -lws2_32 -o getip.exe
- 运行:getip 主机名
- 结果:
主机名 域名:DESKTOP-B1O7B1S
查询结果:
主机名:DESKTOP-B1O7B1S
地址类型:AF_INET
地址长度:4
IP地址#1:169.255.255.255
IP地址#2:192.255.255.255
IP地址#3:192.255.255.255
------------------------------------------------
主机名 域名:www.baidu.com
查询结果:
主机名:www.a.shifen.com
别名#1:www.baidu.com
地址类型:AF_INET
地址长度:4
IP地址#0:14.215.177.38
程序步骤:
- 对Windows Sockets的动态链接库WS2_32.dll进行初始化。
- 获取域名或主机名 本机的话用gethostname进行解析。
- 用gethostbyname获取所需要的信息 返回struct hostent类型。
struct hostent
{
char *h_name; //地址的正式主机名
char **h_aliases; //主机别名,是一个以NULL结束的别名数组
short h_addrtype; //地址类型,通常是AF_INET
short h_length; //地址的字节长度
char **h_addr_list;//一个以网络字节顺序表示的以NULL结束的主机地址列表
#define h_addr h_addr_list[0] //定义列表项的第一项为默认主机地址h_addr
}
struct in_addr: 表示一个32位的IPv4地址:
struct in_addr
{
unsigned long s_addr;
};
代码:
#include <stdio.h>
#include <winsock2.h>
int main(int argc, char *argv[])
{
char *host_name; //要查询的主机名
char local_host[256];
if(argc != 2)
{
printf("输入错误!\n");
printf("用法:getip 主机名\n");
printf("提示:getip localhost");
return 1;
}
//1、对Windows Sockets的动态链接库WS2_32.dll进行初始化
//WORD sockVersion = MAKEWORD(2, 2); ====>设定socket版本为2.2
WSADATA wsaData;
int retvalue = WSAStartup(MAKEWORD(2, 2), &wsaData);
if(retvalue != 0)
{
printf("WSAStartup 失败:%d\n", retvalue);
return 1;
}
//2、查询获取的是不是本地ip,如果是则获取本机的主机名
if(strcmp(argv[1], "localhost") == 0)
{
// gethostname返回本地主机的标准主机名
retvalue = gethostname(local_host, sizeof(local_host));
if(retvalue != 0)
{
printf("获取本地主机名失败:%d\n", retvalue);
return 1;
}
host_name = local_host;
}
else
host_name = argv[1];
printf("主机名 域名:%s\n", host_name);
//3、gethostbyname用域名或主机名获取IP地址 返回struct hostent类型
struct hostent *remotehost = gethostbyname(host_name);
//对返回的结果进行判断
if(remotehost == NULL)
{
//获取错误类型
DWORD errcode = WSAGetLastError();
if(errcode == WSAHOST_NOT_FOUND)
{
printf("主机没有找到!");
return 1;
}
else if(errcode == WSANO_DATA)
{
printf("没找到相应的数据!");
return 1;
}
else
{
printf("调用函数失败:%ld\n", errcode);
return 1;
}
}
else
{
//获取地址类型和地址长度
int i = 0;
printf("查询结果:\n");
printf("\t主机名:%s\n", remotehost->h_name);
//palias二级指针指向了存储别名地址的空间 *palias储别名地址
for(char **palias = remotehost->h_aliases; *palias != 0; palias++)
{
printf("\t别名#%d:%s\n", ++i, *palias);
}
printf("\t地址类型:");
switch(remotehost->h_addrtype)
{
case AF_INET:
printf("AF_INET\n");
break;
case AF_NETBIOS:
printf("AF_NETBIOS\n");
break;
default:
printf("%d\n", remotehost->h_addrtype);
break;
}
printf("\t地址长度:%d\n", remotehost->h_length);
//如果返回的是IPv4地址,则输出查询到的结果 inet_ntoa:将网络二进制数字转为网络地址
//inet_aton:将网络地址转为网络二进制数字
//char *inet_ntoa (struct in_addr);
int j = 0;
struct in_addr addr;
if(remotehost->h_addrtype == AF_INET)
{
while(remotehost->h_addr_list[j] != NULL)
{
addr.s_addr = *(u_long *)remotehost->h_addr_list[j++];
// addr.s_addr = *(u_long *)(*remotehost->h_addr_list++);
// j++;
printf("\tIP地址#%d:%s\n", j, inet_ntoa(addr));
// printf("\tIP地址#%d:%s\n", inet_ntoa(*(struct in_addr*)remotehost->h_addr_list[j++]));
// printf("\tIP地址#%d:%s\n", inet_ntoa(*(struct in_addr*)(*remotehost->h_addr_list++)));
// j++;
}
}
else if(remotehost->h_addrtype == AF_NETBIOS)
{
printf("返回的是ENTBIOS地址");
}
//释放WinSock动态链接库相关的资源
WSACleanup();
}
return 0;
}