gpt4 book ai didi

c - 为什么 sin_family 成员存在?

转载 作者:太空宇宙 更新时间:2023-11-04 00:56:46 26 4
gpt4 key购买 nike

如果我正在使用 struct sockaddr_in,地址族已经在我创建的任何套接字中指定。

此外,如果 sin_family 成员必须始终为 AF_INET,则使用 sin_family 成员似乎是多余的。

那么为什么 sin_family 成员存在呢?

最佳答案

的确,struct sockaddr_insin_family 成员必须始终是AF_INET。这样做的原因是可以判断通用套接字描述符的实际类型。

struct sockaddr_in是套接字地址描述符的几种类型之一,根据网络协议(protocol)有不同的成员:

struct sockaddr_in {
sa_family_t sin_family; /* always AF_INET */
in_port_t sin_port;
struct in_addr sin_addr;
};

struct sockaddr_in6 {
sa_family_t sin6_family; /* always AF_INET6 */
in_port_t sin6_port;
uint32_t sin6_flowinfo;
struct in6_addr sin6_addr;
uint32_t sin6_scope_id;
};

struct sockaddr_un {
sa_family_t sun_family; /* always AF_UNIX */
char sun_path[108];
};

/* and more ... */

一些 POSIX 函数,如 bindaccept 接受一个指向 struct sockaddr 的指针,这是一个只有初始 sa_family_t 的虚拟类型sa_family; 成员。因此,它们或其他代码可以通过检查协议(protocol)族来处理转换为 [const] struct sockaddr* 指针的任何一个结构,然后转换回基于该值的实际类型。

例如,围绕 bind 的日志包装器可能会执行以下操作:

int loggable_bind(int sockfd, const struct sockaddr* addr, socklen_t addrlen)
{
bool do_log = logging_enabled();
if (do_log) {
switch (addr->sa_family) {
case AF_INET: {
const struct sockaddr_in* addr_in = (const struct sockaddr_in*) addr;
printf("bind: fd=%d family=AF_INET addr=%s port=%u",
sockfd,
inet_ntoa(addr_in->sin_addr),
(unsigned) addr_in->sin_port);
break;
}
case AF_INET6: {
const struct sockaddr_in6* addr_in6 = (const struct sockaddr_in6*) addr;
printf("bind: fd=%d family=AF_INET6 addr=%.*s port=%u",
sockfd,
sizeof(addr_in6->sin6_addr.s6_addr),
(const char*) addr_in6->sin6_addr.s6_addr,
(unsigned) addr6_in->sin6_port);
break;
}
case AF_UNIX: {
const struct sockaddr_un* addr_un = (const struct sockaddr_un*) addr;
if (addrlen == sizeof(sa_family_t)) {
printf("bind: fd=%d family=AF_UNIX Unnamed");
} else if (addr_un->sun_path[0] == '\0') {
printf("bind: fd=%d family=AF_UNIX Abstract, path='");
for (size_t i=1; i<(addrlen-offsetof(struct sockaddr_un, sun_path)); ++i) {
int c = (unsigned char) addr_un->sun_path[i];
if (isprint(c))
putchar(c);
else
printf("\\x%02x", (unsigned) c);
}
putchar('\'');
} else {
printf("bind: fd=%d family=AF_UNIX Named, path=%s",
fd, addr_un->sun_path);
}
break;
}
default:
printf("bind: fd=%d family=%u", fd, (unsigned) addr->sa_family);
break;
}
}
int result = bind(fd, addr, addrlen);
if (do_log) {
int local_err = errno;
printf(" -> %d\n", result);
if (result < 0)
printf(" errno=%d: %s\n", local_err, strerror(local_err));
}
return result;
}

关于c - 为什么 sin_family 成员存在?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57779761/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com