使用getnameinfo实现网络编程中IP地址和域名转换的详解

一、getnameinfo函数概述

getnameinfo是网络编程中常用的函数之一,它的作用是将IP地址和端口转换成可读的主机名和服务名。

该函数定义于sys/socket.h和netdb.h头文件中,它的原型如下:

int getnameinfo(const struct sockaddr *restrict sa, socklen_t salen,
                char *restrict host, socklen_t hostlen,
                char *restrict serv, socklen_t servlen, int flags);

其中,参数sa是一个指向要转换的sockaddr结构体的指针,salen是这个结构体的长度;

参数host和serv分别是主机名和服务名的存放缓冲区,hostlen和servlen是它们的长度;

参数flags的使用可以决定返回结果的格式,常用的值有NI_NUMERICHOST和NI_NUMERICSERV。

二、将IP地址转换为主机名

在使用getnameinfo函数将IP地址转换为主机名时,我们需要先将IP地址存放到一个sockaddr结构体中。

下面是具体的转换过程:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

int main(int argc, char *argv[]) {
    struct addrinfo hints, *res;
    char ip_str[INET6_ADDRSTRLEN];
    void *addr;
    if (argc != 2) {
        fprintf(stderr,"usage: %s ip\n", argv[0]);
        exit(1);
    }
    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_UNSPEC; // Allow IPv4 or IPv6 
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE; // For wildcard IP address 
    if (getaddrinfo(argv[1], NULL, &hints, &res) != 0) {
        fprintf(stderr, "getaddrinfo error\n");
        exit(1);
    }
    // convert address to a string 
    if (res->ai_family == AF_INET) { // IPv4 
        struct sockaddr_in *ipv4 = (struct sockaddr_in *)res->ai_addr;
        addr = &(ipv4->sin_addr);
    } else { // IPv6 
        struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)res->ai_addr;
        addr = &(ipv6->sin6_addr);
    }
    // convert the IP to a string and print it 
    inet_ntop(res->ai_family, addr, ip_str, sizeof(ip_str));
    printf("IP address: %s\n", ip_str);
    // convert IP to host name 
    char host[NI_MAXHOST];
    if (getnameinfo(res->ai_addr, res->ai_addrlen, host, NI_MAXHOST, NULL, 0, 0) != 0) {
        fprintf(stderr, "getnameinfo error\n");
        exit(1);
    }
    printf("Host name : %s\n", host);
    freeaddrinfo(res);
    return 0;
}

在这个例子中,我们通过命令行参数传入了需要转换的IP地址,然后使用getaddrinfo函数将这个地址转换为一个sockaddr结构体。

接着,我们使用inet_ntop函数将IP地址转换为一个字符串,并打印出来。

最后,我们使用getnameinfo函数将该IP地址转换为主机名,并打印出来。

需要注意的是,在使用getnameinfo函数时,可以通过flags参数来控制输出的格式。

三、将主机名转换为IP地址

和将IP地址转换为主机名类似,我们先需要用getaddrinfo函数将主机名转换为一个sockaddr结构体,然后再调用getnameinfo函数来将它转换为IP地址。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

int main(int argc, char *argv[]) {
    struct addrinfo hints, *res;
    char ip_str[INET6_ADDRSTRLEN];
    if (argc != 2) {
        fprintf(stderr,"usage: %s hostname\n", argv[0]);
        exit(1);
    }
    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    if (getaddrinfo(argv[1], NULL, &hints, &res) != 0) {
        fprintf(stderr, "getaddrinfo error\n");
        exit(1);
    }
    // convert the socket address to a string and print it 
    int i;
    for(i = 1, res = res->ai_next; res; res = res->ai_next, ++i) {
        void *addr;
        char* ipver;
        if (res->ai_family == AF_INET) { // IPv4 
            struct sockaddr_in *ipv4 = (struct sockaddr_in *)res->ai_addr;
            addr = &(ipv4->sin_addr);
            ipver = "IPv4";
        } else { // IPv6 
            struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)res->ai_addr;
            addr = &(ipv6->sin6_addr);
            ipver = "IPv6";
        }
        inet_ntop(res->ai_family, addr, ip_str, sizeof ip_str);
        printf("%s address %d: %s\n", ipver, i, ip_str);
    }
    freeaddrinfo(res);
    return 0;
}

在这个例子中,我们通过命令行参数传入了需要转换的主机名,然后使用getaddrinfo函数将该主机名转换为一个sockaddr结构体。

然后,我们遍历所有的结果,将其中的IP地址转换为字符串,并打印出它们的版本(IPv4或IPv6)和序号。

四、小结

getnameinfo是网络编程中一个非常重要的函数,它可以方便地将IP地址和端口转换为可读的主机名和服务名。

在使用该函数时需要注意一些细节,比如flags参数可以控制输出的格式。通过这篇文章的介绍,相信读者已经对getnameinfo函数有了更深入的了解。

原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/233971.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
小蓝小蓝
上一篇 2024-12-11 17:12
下一篇 2024-12-11 17:12

相关推荐

  • cmd看地址

    本文将从多个方面详细阐述cmd看地址,包括如何查看本机IP地址、如何查看路由器IP、如何查看DNS服务器IP等等。 一、查看本机IP地址 要查看本机IP地址,首先需要打开cmd窗口…

    编程 2025-04-29
  • Kubesphere私有域名配置

    本文将从以下几个方面介绍如何在Kubesphere中配置私有域名: 一、什么是Kubesphere私有域名 Kubesphere是基于Kubernetes的开源多云容器化平台,它允…

    编程 2025-04-29
  • 尚硅谷官网地址用法介绍

    尚硅谷是国内一家领先的技术培训机构,提供了众多IT职业的培训,包括Java、Python、大数据、前端、人工智能等方向。其官网地址为http://www.atguigu.com/。…

    编程 2025-04-29
  • 两个域名指向同一IP不同端口打开不同网页的实现方法

    本文将从以下几个方面详细阐述两个域名指向同一个IP不同端口打开不同网页的实现方法。 一、域名解析 要实现两个域名指向同一个IP不同端口,首先需要进行域名解析。在域名解析的时候,将这…

    编程 2025-04-28
  • Idea2022变更Git地址

    本文将从以下几个方面对Idea2022变更Git地址进行详细阐述: 一、GitHub上修改Git仓库地址 1、登录GitHub,找到需要修改的Git仓库 2、在代码页面点击右上角的…

    编程 2025-04-28
  • electron-egg打包后请求地址错误解决方法用法介绍

    本文将从多个方面对electron-egg打包后请求地址错误进行详细阐述,并给出解决方法。 一、electron-egg打包后请求地址错误的表现 在使用 electron-egg …

    编程 2025-04-27
  • PHP获取301跳转后的地址

    本文将为大家介绍如何使用PHP获取301跳转后的地址。301重定向是什么呢?当我们访问一个网页A,但是它已经被迁移到了另一个地址B,此时若服务器端做了301重定向,那么你的浏览器在…

    编程 2025-04-27
  • Python如何判断IP地址合法性

    IP地址是网络通信的基础,因此判断IP地址合法性是编程中常见的问题。Python作为一门强大的编程语言,提供了多种方法来判断IP地址的合法性。 一、判断IP地址格式是否正确 IP地…

    编程 2025-04-27
  • Python处理“该请求的地址无效”的解决方法

    本文将从以下几个方面为大家详细阐述在python中处理“该请求的地址无效”的解决方法。 一、检查URL地址是否正确 当我们在使用Python发送网络请求时,如果URL地址不正确,就…

    编程 2025-04-27
  • Linux sync详解

    一、sync概述 sync是Linux中一个非常重要的命令,它可以将文件系统缓存中的内容,强制写入磁盘中。在执行sync之前,所有的文件系统更新将不会立即写入磁盘,而是先缓存在内存…

    编程 2025-04-25

发表回复

登录后才能评论