网络编程——域名及网络地址

参考

  1. 《TCP/IP网络编程》 尹圣雨

域名及网络地址

域名系统

DNS是对IP地址和域名进行相互转换的系统,其核心是DNS服务器

域名

提供网络服务的服务器端是IP地址区分的,将容易记、易表述的域名分配并取代IP地址

DNS服务器

域名是赋予服务器的虚拟地址,域名服务器将虚拟地址转化为实际地址。所有计算机中都记录着默认DNS服务器地址

计算机内置的默认DNS服务器并不知道网络上所有域名的IP地址信息。若该DNS服务器无法解析,则会询问其他DNS服务器,并提供给用户(https://blog.csdn.net/beilizhang/article/details/119598903)

ping命令

ping命令用来验证IP数据报是否到达目的地,但执行过程中会同时经过“域名到IP地址”的转换过程,因此可以通过此命令查看IP地址

nslookup命令

在Linux系统中输入后,会提示进一步输入信息,此时可以输入server得到默认DNS服务器地址

IP地址和域名直接的转换

利用域名获取IP地址
#include <netdb.h>

struct hostent* gethostbyname(const char* hostname);

成功时返回hostent结构体地址,失败时返回NULL指针

返回时,地址信息装入hostent结构体

struct hostent
{
    char* h_name;               // official name
    char** h_aliases            // alias list
    int h_addrtype;             // host address type
    int h_length;               // address length
    char** h_addr_list          // address list
};

(1)h_name
该变量中存有官方域名(Official domain name)。官方域名代表某一主页,但实际上,一些著名公司的域名并未用官方域名注册

(2)h_aliases
可以通过多个域名访问同一主页。同一IP可以绑定多个域名,因此,除官方域名外还可指定其他域名。这些信息可以通过h_aliases获得

(3)h_addrtype
gethostbyname函数不仅支持IPv4,还支持IPv6。因此可以通过此变量获取保存在h_addr_list的IP地址的地址族信息。若是IPv4,则此变量存有AF_INET

(4)h_length
保存IP地址长度。若是IPv4地址,因为是4个字节,则保存4;IPv6时,因为是16个字节,故保存16

(5)h_addr_list
通过此变量以整数形式保存域名对应的IP地址。另外,用户较多的网络有可能分配多个IP给同一域名,利用多个服务器进行负载均衡。此时同样可以通过此变量获取IP地址信息。h_addr_list指向字符串指针数组(由多个字符串地址构成的数组)。字符串指针数组中的元素实际指向的是(实际保存的是)in_addr结构体变量地址值而非字符串

利用域名获取IP地址示例
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netdb.h>
void error_handling(char* message);

int main(int argc, char* argv[])
{
    int i;
    struct hostent* host;
    if (argc != 2)
    {
        printf("Usage : %s <addr>\n", argv[0]);
        exit(1);
    }

    host = gethostbyname(argv[1]);
    if (!host)
    {
        error_handling("gethost...error");
    }

    printf("Official name: %s \n", host->h_name);           // 输出官方域名
    for (i = 0; host->h_aliases[i]; i++)
    {
        printf("Aliases %d: %s \n", i + 1, host->h_aliases[i]);   // 输出官方域名以外的域名
    }
    printf("Address type: %s \n", (host->h_addrtype == AF_INET) ? "AF_INET" : "AF_INET6");
    for (i = 0; host->h_addr_list[i]; i++)
    {
        printf("IP addr %d: %s \n", i + 1, inet_ntoa(*(struct in_addr*)host->h_addr_list[i])); // 输出IP地址信息
    }
    return 0;
}

void error_handling(char* message)
{
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}
利用IP地址获取域名
#include <netdb.h>

struct hostent* gethostbyaddr(const char* addr, socklen_t len, int family);

成功时返回hostent结构体变量地址值,失败时返回NULL指针

(1)addr
含有IP地址信息的in_addr结构体指针。为了同时传递IPv4地址之外的其他信息,该变量的类型声明为char指针

(2)len
向第一个参数传递的地址信息的字节数,IPv4时为4,IPv6时为6

(3)family
传递地址族信息,IPv4时位AF_INET,IPv6时为AF_INET6

利用IP地址获取域名示例
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netdb.h>
void error_handling(char* message);

int main(int argc, char* argv[])
{
    int i;
    struct hostent* host;
    struct sockaddr_in addr;
    if (argc != 2)
    {
        printf("Usage : %s <IP>\n", argv[0]);
        exit(1);
    }

    memset(&addr, 0, sizeof(addr));
    addr.sin_addr.s_addr = inet_addr(argv[1]);
    host = gethostbyaddr((char*)&addr.sin_addr, 4, AF_INET);
    if (!host)
    {
        error_handling("gethost...error");
    }

    printf("Official name: %s \n", host->h_name);
    for (i = 0; host->h_aliases[i]; i++)
    {
        printf("Aliases %d: %s \n", i + 1, host->h_aliases[i]);
    }
    printf("Address type: %s \n", (host->h_addrtype == AF_INET) ? "AF_INET" : "AF_INET6");
    for (i = 0; host->h_addr_list[i]; i++)
    {
        printf("IP addr %d: %s \n", i + 1, inet_ntoa(*(struct in_addr*)host->h_addr_list[i]));
    }
    return 0;
}

void error_handling(char* message)
{
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}

基于Windows的实现

Windows平台下也有同名函数,与Linux中没有区别。但在最新的VS下已不能使用,需要使用<WS2tcpip.h>中的getaddrinfo()和getnameinfo()

利用域名获取IP地址
#include <stdio.h>
#include <stdlib.h>
#include <WinSock2.h>

void ErrorHandling(char* message);

int main(int argc, char* argv[])
{
	WSADATA wsaData;
	int i;
	struct hostent* host;
	if (argc != 2)
	{
		printf("Usage : %s <addr>\n", argv[0]);
		exit(1);
	}
	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
	{
		ErrorHandling("WSAStartup() error!");
	}

	host = gethostbyname(argv[1]);
	if (!host)
	{
		ErrorHandling("gethost...error");
	}

	printf("Official name: %s \n", host->h_name);
	for (i = 0; host->h_aliases[i]; i++)
	{
		printf("Aliases %d: %s \n", i + 1, host->h_aliases[i]);
	}
	printf("Address type: %s \n", (host->h_addrtype == AF_INET) ? "AF_INET" : "AF_INET6");
	for (i = 0; host->h_addr_list[i]; i++)
	{
		printf("IP addr %d: %s \n", i + 1, inet_ntoa(*(struct in_addr*)host->h_addr_list[i]));
	}
	WSACleanup();
	return 0;
}

void ErrorHandling(char* message)
{
	fputs(message, stderr);
	fputc('\n', stderr);
	exit(1);
}
利用IP地址获取域名
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <WinSock2.h>
void ErrorHandling(char* message);

int main(int argc, char* argv[])
{
	WSADATA wsaData;
	int i;
	struct hostent* host;
	SOCKADDR_IN addr;
	if (argc != 2)
	{
		printf("Usage : %s <IP>\n", argv[0]);
		exit(1);
	}
	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
	{
		ErrorHandling("WSAStartup() error!");
	}

	memset(&addr, 0, sizeof(addr));
	addr.sin_addr.s_addr = inet_addr(argv[1]);
	host = gethostbyaddr((char*)&addr.sin_addr, 4, AF_INET);
	if (!host)
	{
		ErrorHandling("gethost...error");
	}

	printf("Official name: %s \n", host->h_name);
	for (i = 0; host->h_aliases[i]; i++)
	{
		printf("Aliases %d: %s \n", i + 1, host->h_aliases[i]);
	}
	printf("Address type: %s \n", (host->h_addrtype == AF_INET) ? "AF_INET" : "AF_INET6");
	for (i = 0; host->h_addr_list[i]; i++)
	{
		printf("IP addr %d: %s \n", i + 1, inet_ntoa(*(struct in_addr*)host->h_addr_list[i]));
	}
	WSACleanup();
	return 0;
}

void ErrorHandling(char* message)
{
	fputs(message, stderr);
	fputc('\n', stderr);
	exit(1);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值