【发布时间】:2017-01-18 20:32:35
【问题描述】:
这是一个简单的程序,展示了我们在编写套接字程序时通常如何将 struct sockaddr * 类型转换为 struct sockaddr_in * 或 struct sockaddr_in6 *。
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
int main()
{
struct addrinfo *ai;
printf("sizeof (struct sockaddr): %zu\n", sizeof (struct sockaddr));
printf("sizeof (struct sockaddr_in): %zu\n", sizeof (struct sockaddr_in));
printf("sizeof (struct sockaddr_in6): %zu\n", sizeof (struct sockaddr_in6));
if (getaddrinfo("localhost", "http", NULL, &ai) != 0) {
printf("error\n");
return EXIT_FAILURE;
}
if (ai->ai_family == AF_INET) {
struct sockaddr_in *addr = (struct sockaddr_in *) ai->ai_addr;
printf("IPv4 port: %d\n", addr->sin_port);
} else if (ai->ai_family == AF_INET6) {
struct sockaddr_in6 *addr = (struct sockaddr_in6 *) ai->ai_addr;
printf("IPv6 port: %d\n", addr->sin6_port);
}
return 0;
}
Beej's Guide to Network Programming 也在第 10 页推荐了这个。
为了处理 struct sockaddr,程序员创建了一个并行结构:struct sockaddr_in(“in”代表“Internet”)用于 IPv4。
这是重要的一点:指向 struct sockaddr_in 的指针可以转换为指向 struct sockaddr 的指针,反之亦然。所以即使 connect() 想要一个 struct sockaddr*,你仍然可以使用一个 struct sockaddr_in 并在最后一刻强制转换它!
但从another question 的讨论来看,这似乎只是一个 hack,不是 C 标准中有效的 C 代码。
特别是,请参阅提到的AnT's answer,
至于在 struct sockaddr *、struct sockaddr_in * 和 struct sockaddr_in6 * 之间进行强制转换的流行技术——这些只是与 C 语言无关的技巧。它们只是在实践中起作用,但就 C 语言而言,该技术是无效的。
因此,如果我们用来进行套接字编程的这种技术(以及书籍也推荐的技术)是无效的,那么重写上述代码使其也是符合 C 标准的有效 C 代码的有效方法是什么?
【问题讨论】:
-
Beej 的网络编程指南 在网络编程技术方面通常是坚如磐石的。如果包含的内容完全不正确,这种情况很少见。
-
你的报价中提到的方式是接口的意图。它已经持续了三十多年。没有其他必要了。