这是一个简单的程序,展示了我们通常如何类型转换struct sockaddr *
to struct sockaddr_in *
or 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 的网络编程指南 http://beej.us/guide/bgnet/output/print/bgnet_A4.pdf第 10 页也推荐了此内容。
为了处理 struct sockaddr,程序员创建了一个并行结构:struct sockaddr_in(“in”代表“Internet”)与 IPv4 一起使用。
这是重要的一点:指向 struct sockaddr_in 的指针可以转换为指向 struct sockaddr 的指针,反之亦然。因此,即使 connect() 需要一个 struct sockaddr*,您仍然可以使用 struct sockaddr_in 并在最后一刻强制转换它!
但从讨论来看另一个问题 https://stackoverflow.com/q/39425409/1175080,看来这只是一个 hack,不是符合 C 标准的有效 C 代码。
特别是,请参阅安特的回答 https://stackoverflow.com/a/39425915/1175080其中提到,
至于流行的 struct sockaddr *、struct sockaddr_in * 和 struct sockaddr_in6 * 之间的转换技术 - 这些只是与 C 语言无关的 hack。它们只是在实践中起作用,但对于 C 语言而言,该技术是无效的。
那么,如果我们用来进行套接字编程的技术(以及书籍中推荐的技术)无效,那么重写上述代码以使其成为符合 C 标准的有效 C 代码的有效方法是什么?