私はCでのソケットプログラミングを調べていますが、なぜとのような関数でパラメーターとそのパラメーターの長さを渡さなければならないのか興味がありますbind()
かconnect()
?sizeof()
関数内で使用しないのはなぜですか?
2 に答える
同じAPIで多くの異なるタイプのプロトコルを処理するためのシンプルでシンプルな方法を提供するためです。
ソケットは(@larsmanによって指摘されているように)多くの異なる基礎となるプロトコルを使用できるため、呼び出しは、渡されている構造のタイプを正確に知ることができません。さまざまなstruct sockaddr
タイプで行われているいくつかの基本的な「継承」があります。
また、上位互換性もあります。ライブラリの1つのバージョンに対してコンパイルされたバイナリが、アドレスタイプが拡張された可能性のある新しいバージョンに対して実行される可能性があります(たとえば、IPv6をサポートするため)。
呼び出し元のサイズのアイデアを呼び出された関数に渡すことにより、呼び出された関数はメモリを上書きしないように注意することができます。
私はあなたに3番目の議論があると思います
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
関数内で行うことはできませんsizeof(addr)
。これは、指定された構造体ではなく、ポインターのサイズを返すだけだからです。sizeof(struct sockaddr)
また、異なるアドレスファミリ(ローカルソケット、IPv4、IPv6、エキゾチックネットワークプロトコル)のサイズが異なるため、機能しませんsockaddr
。
たとえば、IPv4ソケットの場合、
struct sockaddr_in my_addr;
// set up my_addr
bind(fd, (struct sockaddr *)my_addr, sizeof(struct sockaddr_in));
ただし、ローカル(Unix)ドメインソケットの場合sockaddr_un
は、長さが異なる可能性のあるaを渡します。
[私のLinuxボックスでは、sizeof(struct sockaddr_in) == 16
しかしsizeof(struct sockaddr_un) == 110
。]
オブジェクト指向プログラミングに慣れている場合は、sockaddr
ファミリを動的型付けの(浅い)クラス階層と考えることができます。struct sockaddr
は抽象基本クラス、、bind
などconnect
はメソッドです。Cには動的型付けが組み込まれていないため、エミュレートする必要があり、構造体のサイズを渡すことはその一部です。