我是IPV6的新手,我需要将我的项目从IPV4风格移植到双栈支持风格,我在某个点上陷入了困境。我需要了解存储在sockaddr_storage中的地址的IP版本,而无需检查其家族。
我写了一个代码并尝试使用"inet_ntop"函数,但它将所有族相互转换,没有任何错误。例如,它将";fe80::9110:403c:1f99:acb";IP到";0.0.0.0";如果我试图使用AF_INET转换它,并且它是一个有效的IPV4地址,那么我的代码就会得到错误的操作。
请检查下面的代码;
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdbool.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <errno.h>
#include "ipv6_util.h"
#define SUCCESS (EXIT_SUCCESS)
#define FAIL (EXIT_FAILURE)
#define UNUSED(__val__) (void)(__val__)
#define PORT 9999
#define CONN_COUNT 1
#define BUFFER_SIZE 1024
#define QUIT_MESSAGE "quit"
#define ACK_MESSAGE "ack"
#define IPV6_IP_1 "::1"
#define IPV4_IP_1 "127.0.0.1"
#define IPV4_IP_2 "192.168.2.254"
#define IPV4_IP_3 "100.100.100.100"
#define IPV6_IP_2 "fe80::9110:403c:1f99:eacb"
void ipv6_util_get_ipadd_ver_from_addr2(const struct sockaddr_storage *ipaddress)
{
char address_buf[128] = {0};
memset(address_buf, 0, 128);
if (inet_ntop(AF_INET, &((struct sockaddr_in *)ipaddress)->sin_addr, address_buf, 128)) {
printf("it is ipv4n");
printf("buff: %s %dn", address_buf, __LINE__);
//return;
}
memset(address_buf, 0, 128);
if (inet_ntop(AF_INET6, &((struct sockaddr_in6 *)ipaddress)->sin6_addr, address_buf, 128)) {
printf("it is ipv6n");
printf("buff: %s %dn", address_buf, __LINE__);
//return;
}
}
int main(void)
{
struct sockaddr_storage dumm;
memset(&dumm, 0, sizeof(struct sockaddr_storage));
printf("n");
memset(&dumm, 0, sizeof(struct sockaddr_storage));
if (inet_pton(AF_INET6, IPV6_IP_1, &((struct sockaddr_in6 *)&dumm)->sin6_addr) != 1) {
printf("error %dn", __LINE__);
}
ipv6_util_get_ipadd_ver_from_addr2(&dumm);
printf("nn");
memset(&dumm, 0, sizeof(struct sockaddr_storage));
if (inet_pton(AF_INET, IPV4_IP_1, &((struct sockaddr_in *)&dumm)->sin_addr) != 1) {
printf("error %dn", __LINE__);
}
ipv6_util_get_ipadd_ver_from_addr2(&dumm);
printf("nn");
memset(&dumm, 0, sizeof(struct sockaddr_storage));
if (inet_pton(AF_INET, IPV4_IP_2, &((struct sockaddr_in *)&dumm)->sin_addr) != 1) {
printf("error %dn", __LINE__);
}
ipv6_util_get_ipadd_ver_from_addr2(&dumm);
printf("nn");
memset(&dumm, 0, sizeof(struct sockaddr_storage));
if (inet_pton(AF_INET6, IPV6_IP_2, &((struct sockaddr_in6 *)&dumm)->sin6_addr) != 1) {
printf("error %dn", __LINE__);
}
ipv6_util_get_ipadd_ver_from_addr2(&dumm);
printf("nn");
memset(&dumm, 0, sizeof(struct sockaddr_storage));
if (inet_pton(AF_INET, IPV4_IP_3, &((struct sockaddr_in *)&dumm)->sin_addr) != 1) {
printf("error %dn", __LINE__);
}
ipv6_util_get_ipadd_ver_from_addr2(&dumm);
printf("nn");
return SUCCESS;
return 0;
}
对于这个代码,我得到了这个输出;
it is ipv4
buff: 0.0.0.0 39
it is ipv6
buff: ::1 46
it is ipv4
buff: 127.0.0.1 39
it is ipv6
buff: :: 46
it is ipv4
buff: 192.168.2.254 39
it is ipv6
buff: :: 46
it is ipv4
buff: 0.0.0.0 39
it is ipv6
buff: fe80::9110:403c:1f99:eacb 46
it is ipv4
buff: 100.100.100.100 39
it is ipv6
buff: :: 46
所以我找不到它的原始版本。我该怎么做?
谢谢你的帮助。
地址族仅在ss_family
或sa_family
成员中。
使用getaddrinfo
将sockaddr
转换为可读格式。
您不应该使用sockaddr_storage
作为函数的参数,而是使用sockaddr
并将sockaddr_storage
强制转换为sockaddr
。
我按照Cheatah的建议尝试了getnameinfo函数,结果和我原来的帖子一样。我的意思是,在某个时刻,我似乎不得不将switchcase与sa_familiy一起使用。
谢谢大家。