#include <sys/socket.h> // 这个好像在这里可以省略
#include <netinet/in.h> // 提供struct in_addr
#include <arpa/inet.h> // 提供inet_ntoa()
char *inet_ntoa(struct in_addr in);
DESCRIPTION
The inet_ntoa() function converts the Internet host address in, given in network byte order, to a string in IPv4 dotted-decimal notation. The string is returned in a statically allocated buffer, which subsequent call will overwrite.
函数的作用是:将以网络字节序给出的网络主机地址 in 转换成以点分十进制表示的字符串(如127.0.0.1)。结果作为函数返回结果返回。
这里简单说下参数中的struct in_addr结构变量。
struct sockaddr_in {
sa_family_t sin_family; /* 地址族: AF_INET */
u_int16_t sin_port; /* 按网络字节次序的端口 */
struct in_addr sin_addr; /* internet地址 */
};
/* Internet地址. */
struct in_addr {
u_int32_t s_addr; /* 按网络字节次序的地址 */
};
奥,又顺带跑出来一个struct sockaddr_in结构。要是大家有简单学过网络编程,应该会比较熟悉。该结构第一个成员sin_family表示地址族,它的值主要有:AF_INET表示IPv4,AF_INET6表示IPv6;第二成员表示16bit的端口号;第三个成员就是我们主要说的struct in_addr结构变量,这个结构下只有一个成员,就是32bit的网络字节序表示的IP地址(大家会很奇怪,它喵的只有一个成员还要另外包含在结构里面,其实一开始这个结构里面有很多别的成员,只是后面被删得只剩下这个成员了)。
对了,在网络中传输数据,是以网络字节序(大端序)来传输的。一开始主机也许都是大端的,只是后面的人也许标新立异,就出现了小端序的电脑,导致在进行网络数据传输前,要统一规定,不然同样的数据会有不同的解释。
大端序:高位字节放在低位地址。(地址排序不会变,说大那是形容字节次序,大即高位地址)
小端序:低位字节放在低位地址。
好像聊偏了,让我们重回正轨,用一个例子来进行进一步的理解。
由于在写这个函数的时候,前面也写了别的相关函数,所以对这些函数进行联系(其它函数我也进行了记录,可以看一下哦)。
inet_ntoa.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
char src_hostname[255]; // 用来保存主机名
struct in_addr *src_addr; // 用来保存本机IP(网络字节序)
struct hostent *src_hostent;
char src_ip_str[32]; // 本机IP(点分十进制)
if (gethostname(src_hostname, sizeof(src_hostname)) == -1) {
fprintf(stderr, "无法确定此计算机的主机名.\n");
exit(EXIT_FAILURE);
}
src_hostent = gethostbyname(src_hostname);
if (src_hostent == NULL) {
fprintf(stderr, "源IP地址找不到\n");
exit(EXIT_FAILURE);
}
src_addr = (struct in_addr*) src_hostent->h_addr_list[0];
strncpy(src_ip_str, inet_ntoa(*src_addr), sizeof(src_ip_str));
fprintf(stdout, "Hostname: %s \n", src_hostname);
fprintf(stdout, "IP: %s \n", src_ip_str);
return 0;
}
运行结果:
$ gcc inet_ntoa.c -o inet_ntoa
$ ./inet_ntoa
Hostname: aragne
IP: 127.0.1.1
我现在使用命令 sudo nvim /etc/hosts
进行查看,果真127.0.0.1 对应着aragne。
该例子主要用了三个函数,使用gethostname()函数获取主机名aragne,然后使用gethostbyname()函数,通过域名获取IP地址,然后使用inet_ntoa()函数将网络字节序表示的IP地址转换成我们比较常见的点分十进制表示的IP地址。