从sockaddr_storage中获取IP和端口

8
我有一个包含远程主机IPv4地址和端口的sockaddr_storage结构体。我以前没有见过这些struct,也不确定如何将其转换为可以直接检索IP地址和端口号的struct。我尝试谷歌这个struct,但没有找到任何信息。有什么建议吗?
谢谢

你确定它是 sockaddr_storage 结构体而不是 sockaddr 结构体吗? - Tony The Lion
是的,它是一个sockaddr_storage结构体。 - KaiserJohaan
1
@Tony: sockaddr_storage 是新代码中首选的结构体,它支持多种地址族,包括 IPv4 和 IPv6。 - Remy Lebeau
在新的代码中,最好完全不要为任何sockaddr结构分配存储空间。 getaddrinfo是您应该使用创建sockaddr结构的唯一函数,并且它会自行分配它们。 - R.. GitHub STOP HELPING ICE
2个回答

6
您可以将指针转换为struct sockaddr_in *struct sockaddr_in6 *并直接访问成员,但这可能会引起别名违规和编译错误的问题。更好的方法是使用getnameinfo函数传递指针,并使用NI_NUMERICHOSTNI_NUMERICSERV标志获取地址和端口的字符串表示形式。这种方法的优点是它支持IPv4和IPv6,而且在理论上也支持所有未来的地址类型。您可能需要将指针转换为void *(或者在使用C++时明确转换为struct sockaddr *)才能将其传递给getnameinfo,但这不应该引起任何问题。

我只使用C标准库;从字符串中提取端口听起来很痛苦。如果我事先知道它是Ipv4还是Ipv6,将其转换为sockaddr_in / sockaddr_in6结构体是否没有问题? - KaiserJohaan

4

为了进一步回答上面的问题并提供一个使用 getnameinfo 函数的代码,请查看以下片段:

struct sockaddr_storage client_addr;
socklen_t client_len = sizeof(struct sockaddr_storage);

// Accept client request
int client_socket = accept(server_socket, (struct sockaddr *)&client_addr, &client_len);

char hoststr[NI_MAXHOST];
char portstr[NI_MAXSERV];

int rc = getnameinfo((struct sockaddr *)&client_addr, client_len, hoststr, sizeof(hoststr), portstr, sizeof(portstr), NI_NUMERICHOST | NI_NUMERICSERV);
if (rc == 0) printf("New connection from %s %s", hoststr, portstr);

结果是hoststr分别包含来自struct sockaddr_storage的IP地址,而portstr则包含端口号。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接