2

クライアントソケットがサーバーからメッセージを受信する方法を示す2つの例を見てきました。

例1:

サーバーコード http://man7.org/tlpi/code/online/book/sockets/ud_ucase_sv.c.html

クライアントコード http://man7.org/tlpi/code/online/book/sockets/ud_ucase_cl.c.html

クライアントプログラムはソケットを作成し、そのソケットをアドレスにバインドして、サーバーが応答を送信できるようにします。

if (bind(sfd, (struct sockaddr *) &claddr, sizeof(struct sockaddr_un)) == -1)
    errExit("bind"); // snippet from ud_ucase_cl.c

例2:

サーバーコード http://man7.org/tlpi/code/online/book/sockets/i6d_ucase_sv.c.html

クライアントコード http://man7.org/tlpi/code/online/book/sockets/i6d_ucase_cl.c.html

例2では、​​クライアントコードはそのソケットをアドレスにバインドしません。

質問

サーバーからメッセージを受信するために、クライアントコードがソケットをアドレスにバインドする必要がありますか?

最初の例では、クライアントソケットをアドレスでバインドする必要があるのはなぜですか、2番目の例ではバインドする必要がないのはなぜですか?

4

3 に答える 3

1

何かを接続/送信する前にAF_INET/AF_INET6クライアントソケットをバインドしていない場合、TCP/IPスタックはそれをアウトバウンドアドレスのエフェメラルポートに自動的にバインドします。

これとは異なり、UNIXドメインソケット(AF_UNIX)は送信時に自動的にバインドされないため、SOCK_DGRAMを介してメッセージを送信できますが、応答を取得することはできません。

于 2011-08-01T13:56:20.723 に答える
1

クライアント (TCP) または送信側 (UDP) の場合、呼び出しbind()はオプションです。インターフェイスを指定する方法です。宛先にルーティング可能な 2 つのインターフェイスがあるとします。

eth0: 10.1.1.100/24
eth1: 10.2.2.100/24

route: 10.1.1.0/24 via 10.2.2.254  # router for eth1
       0.0.0.0     via 10.1.1.254  # general router

とだけ言っconnect()ても12.34.56.78、どのローカル インターフェイスが接続のローカル側を提供しているかわかりません。bind()最初に電話することで、これを具体的にします。

同じことが UDP トラフィックにも当てはまりbind()ます。ingsendto()を使用しないと、ランダムな送信元アドレスとポートが使用されbind()ますが、送信元が固有になります。

于 2011-08-01T13:09:10.927 に答える
1

違いは、socket family最初の例では使用しAF_UNIXているのに対し、2 番目の例では使用していることAF_INET6です。Stevens UNPによるとbind、サーバーが応答を送信できるパス名を持つように、Unix クライアント ソケットへのパス名を明示的に指定する必要があります。

... バインドされていない Unix ドメイン データグラム ソケットにデータグラムを送信しても、暗黙的にパス名がソケットにバインドされません。したがって、この手順を省略すると、サーバーの ... への呼び出しrecvfromは null パス名を返します ...

INET{4,6}ソケットは一時ポートに「自動バインド」されるため、これは必要ありません。

于 2011-08-01T13:54:38.767 に答える