ここでは、ソケットプログラムの作成中に通常どおりにstruct sockaddr *
を入力してstruct sockaddr_in *
またはstruct sockaddr_in6 *
をキャストする方法を示す簡単なプログラムを示します。有効なCコードを使用してstruct sockaddr *を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もsockaddr構造体に対処するには10ページ
でこれを推奨しています、プログラマは並列構造作成します:struct sockaddr_in構造体を(「中」「インターネット」用)はIPv4で使用します。
これは重要なビットです。struct sockaddr_inへのポインタは、struct sockaddrへのポインタにキャストすることができます。逆もまた同様です。だからconnect()はstruct sockaddr *を必要としていますが、struct sockaddr_inを使用して直前にキャストすることができます!
しかし、another questionでの議論から、これはちょうどハックであり、C標準の有効なCコードではないようです。特に
、言及AnT's answer、sockaddr構造体の*、構造体のsockaddr_in *と構造体のsockaddr_in6間のキャストとの一般的な技術については
を参照してください* - これらは、C言語とは何の関係もないただのハックです。彼らは実際には動作しますが、C言語に関する限り、その技術は無効です。
したがって、私たちがソケットプログラミングを行うために使用する手法(およびその書籍で推奨されるもの)が無効である場合、それは有効なCコードであるように上記のコードを書き換える有効な方法Cの標準?
* Beej's Guide to Network Programming *は、ネットワークプログラミングのテクニックでは一般的に堅実です。含まれていたものが間違っていたのは稀である。 –
あなたの引用に記載されている方法は、インタフェースによって意図されているものです。 30年以上続いています。他には何も必要ありません。 – EJP