一、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