bind() 関数はsockaddr
へのポインターを受け入れますが、私が見たすべての例で、sockaddr_in
構造が代わりに使用され、sockaddr
にキャストされます。
struct sockaddr_in name;
...
if (bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0)
...
どうしてsockaddr_in
使用される構造体。なぜsockaddr
を準備して渡すだけですか?
単なる慣習ですか?
いいえ、単なる慣習ではありません。
sockaddr
はあらゆる種類のソケット操作の汎用記述子であり、_sockaddr_in
_はIPベースの通信に固有の構造体です(IIRC、「in」は「InterNet」を表します)。私の知る限り、これは一種の「ポリモーフィズム」です:bind()
関数は_struct sockaddr *
_をとるふりをしますが、実際には、適切なタイプの構造が渡されると仮定します;私。 e。最初の引数として指定したソケットのタイプに対応するもの。
これは、bindはIPソケット以外のタイプのソケット、たとえば、sockaddr_unをタイプとして持つUnixドメインソケットをバインドできるためです。 AF_INETソケットのアドレスにはアドレスとしてホストとポートがありますが、AF_UNIXソケットにはファイルシステムパスがあります。
この質問に非常に関連するかどうかはわかりませんが、C
で多くの時間を費やしていない多くの人が見て混乱するので、タイプキャストをより理解しやすくするための追加情報を提供したいと思いますそのようなタイプキャスト。
macOS
を使用しているため、システムのヘッダーファイルに基づいて例を取っています。
_struct sockaddr
_は次のように定義されます。
_struct sockaddr {
__uint8_t sa_len; /* total length */
sa_family_t sa_family; /* [XSI] address family */
char sa_data[14]; /* [XSI] addr value (actually larger) */
};
_
_struct sockaddr_in
_は次のように定義されます。
_struct sockaddr_in {
__uint8_t sin_len;
sa_family_t sin_family;
in_port_t sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
_
非常に基本的なことから始めて、ポインタにはアドレスが含まれています。したがって、_struct sockaddr *
_と_struct sockaddr_in *
_はほぼ同じです。どちらも住所を保存するだけです。関連する違いは、コンパイラがオブジェクトを処理する方法だけです。
したがって、_(struct sockaddr *) &name
_と言うときは、コンパイラをだまして、このアドレスが_struct sockaddr
_型を指していることを伝えるだけです。
それで、ポインターが位置_1000
_を指しているとしましょう。 _struct sockaddr *
_がこのアドレスを格納する場合、構造定義に従ってメンバーを所有する_1000
_からsizeof(struct sockaddr)
までのメモリを考慮します。 _struct sockaddr_in *
_が同じアドレスを格納する場合、_1000
_からsizeof(struct sockaddr_in)
までのメモリを考慮します。
そのポインターを型キャストすると、sizeof(struct sockaddr)
までの同じバイトシーケンスが考慮されます。
_struct sockaddr *a = &name; // consider &name = 1000
_
ここで_a->sa_len
_にアクセスすると、コンパイラは_1000
_から_sockaddr_in
_の場合と同じバイトサイズのsizeof(__uint8_t)
にアクセスします。したがって、これは同じバイトシーケンスにアクセスする必要があります。
_sa_family
_も同じパターンです。
その後、_struct sockaddr
_(typedef
'd 16ビット符号なし整数= 2バイト)からのデータを格納する_in_port_t sin_port
_に14バイトの文字配列があり、_struct in_addr sin_addr
_(単に32ビットipv4アドレス= 4バイト)および_char sin_zero[8]
_(8バイト)。これら3つを合わせて14バイトにします。
これらの3つはこの14バイトの文字配列に格納されており、適切なインデックスにアクセスして再度型キャストすることにより、これら3つにアクセスできます。
user529758の答えは、これを行う理由をすでに説明しています。