I have seen two examples that illustrate how the client socket can receive messages from server.
Example 1:
server code http://man7.org/tlpi/code/online/book/so开发者_如何学Cckets/ud_ucase_sv.c.html
client code http://man7.org/tlpi/code/online/book/sockets/ud_ucase_cl.c.html
The client program creates a socket and binds the socket to an address, so that the server can send its reply.
if (bind(sfd, (struct sockaddr *) &claddr, sizeof(struct sockaddr_un)) == -1)
errExit("bind"); // snippet from ud_ucase_cl.c
Example 2:
server code http://man7.org/tlpi/code/online/book/sockets/i6d_ucase_sv.c.html
client code http://man7.org/tlpi/code/online/book/sockets/i6d_ucase_cl.c.html
In example 2, client code doesn't bind its socket with an address.
Question:
Is it necessary for the client code to bind the socket with an address in order to receive message from server?
Why in the first example, we have to bind the client socket with an address, why we don't have to in the second example?
The difference is the socket family
- first example uses AF_UNIX
, while the second does AF_INET6
. According to Stevens UNP you need to explicitly bind
pathname to Unix client socket so that the server has a pathname to which it can send its reply:
... sending a datagram to an unbound Unix domain datagram socket does not implicitly bind a pathname to the socket. Therefore, if we omit this step, the server's call to recvfrom
... returns a null pathname ...
This is not required for INET{4,6}
sockets since they are "auto-bound" to an ephemeral port.
For the client (TCP) or sender (UDP), calling bind()
is optional; it is a way to specify the interface. Suppose you have two interfaces, which are both routable to your destination:
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
Now if you just say connect()
to 12.34.56.78
, you don't know which local interface furnishes the local side of the connection. By calling bind()
first, you make this specific.
The same is true for UDP traffic: Without bind()
ing, your sendto()
will use a random source address and port, but with bind()
you make the source specific.
If you have not bound AF_INET/AF_INET6 client socket before connecting/sending something, TCP/IP stack will automatically bind it to ephemeral port on outbound address.
Unlike this, UNIX domain sockets (AF_UNIX) do not automatically bind when sending, so you can send messages via SOCK_DGRAM but can't get any replies.
精彩评论