使用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/zh-tw/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

發表回復

登錄後才能評論