一、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
微信掃一掃
支付寶掃一掃