I have used SO_REUSEADDR to have my server which got terminated to restart without complaining that the socket is already in use. I was wondering: are there other uses of SO_REUSEADDR? Has anyone used the socket option for other than said purpose?
For TCP, the primary purpose is to restart a closed/killed process on the same address.
The flag is needed because the port goes into a TIME_WAIT state to ensure all data is transferred.
If two sockets are bound to the same interface and port, and they are members of the same multicast group, data will be delivered to both sockets.
I guess an alternative use would be a security attack to try to intercept data.
(Source)
For UDP, SO_REUSEADDR is used for multicast.
More than one process may bind to the same SOCK_DGRAM UDP port if the bind() is preceded by:
int one = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
In this case, every incoming multicast or broadcast UDP datagram destined to
the shared port is delivered to all sockets bound to the port.
(Source)
The other main use is to allow multiple sockets to bind() to the same port on UDP. You might not think that would come up, but sometimes multiple apps may want to listen on broadcast/multicast addresses with a given port number. It also allows one to bind to the wildcard address, while also binding to a specific address. For instance, Apache might bind to *:80 and 10.11.12.13:80
Related
I need to send a multicast udp from multihomed computer. Found that in case socket is not bound to some specific interface, default interface will be used (whatever it could mean). My question: is it possible to specify something like inaddr_any to send multicast udp from all available interfaces or is it only possible to do that by enumerating all interfaces and manually send from each? Is there a standard for that?
Thank you
You can set which network interface IPv4 multicast packets leave from by setting the IP_MULTICAST_IF socket option. The value passed to setsockopt should be the address of a struct in_addr containing the IP address of the interface in question.
If you want to send a multicast packet on multiple interfaces, you'll need to call sendto multiple times, setting the IP_MULTICAST_IF option before each one.
I'm attempting to have two daemons running on the same port and IP but one is a server and the other is a client. Is there a method using socket options that would allow each socket to have a copy of the packet and let the daemons filter out the messages based on the protocol? It looks like reuse address blocks the first configured port and reuse port might just balance the packet between the two daemons.
Otherwise, I guess create another daemons to read the socket and send the packets to the correct daemon.
Thanks
You are correct at the end, you will need to have a third part that binds to the port and forwards the packets to the correct daemon.
The other way to do it would be to use three ports and use a firewall to redirect from the front end port to the backend ports; but that is a lot more complicated and not portable. But in the end you could use QOS or something. There is a wide range of possible types of use case behind the word protocol.
If the UDP packets you are receiving are multicast or broadcast packets, then you can set SO_REUSEADDR (and, for BSD-based OS's, SO_REUSEPORT) on the socket (using setsockopt()) before bind()-ing the socket, and then both sockets will receive a copy of each incoming UDP packet. (If the UDP packets are regular old unicast packets, OTOH, then doing the above will result in each received packet being received by only one of the two UDP sockets, which isn't what you want).
Note, however: You refer to the two daemons as being a "client" and a "server" -- the implication of those terms is that the two daemons are going to communicate with each other. If that is the case, then the typical approach would be to have the server-daemon bind to a well-known port number, and the client-daemon could bind to any port number (e.g. it could pass 0 as the port-number to bind(), and let the OS choose an available port-number for it). Then the client-daemon could start the conversation by sending one or more UDP packets to the server's well-known port number, and the server can find out which port the client is sending from (and therefore what port to send reply packets to) by examining the fifth argument of its recvfrom() call. In this case there is no need for the two programs to bind to the same port, and therefore no need for packet-forwarding.
My question is whether the socket file descriptor returned from an accept() will inherit the bind device property of the server listener socket.
I am running on Ubuntu 12.04 using gcc 4.4.
I believe the answer is technically no, but in practice you are likely to see little difference.
Binding your listen socket to a device will cause the socket to only listen to connections made to that that device. If you then accept() that socket, you will be returned an FD referencing a socket that was necessarily produced by referencing a connection made to that device. Whilst I believe that socket FD isn't technically speaking bound to that device, I don't think it would make a lot of difference if it was.
For instance, provided you did bind() on your listen socket, the server side IP address will (bind() or no bind() of the socket returned by accept()) be the guaranteed to be an IP address of the device you bound to. And bind() or no bind() of the socket returned by accept(), if your socket is an IP socket (TCP or UDP is irrelevant), the egress interface for packets is determined by the routing table, and not what interface the socket is bound to. For IP sockets, the bind device is really only relevant to listening. So the socket will behave like it is bound, but (AFAIK) is not technically bound itself.
If you create a socket via socket(2), assign an address to it via bind(2), optionally set options on it via setsockopt(2), mark it as a passive socket by passing it to listen(2), and then pass it to accept(2), then on success accept() returns the file descriptor of a connected socket whose local endpoint is consistent with the characteristics of the socket passed to accept(). In particular, whatever address and any device you assigned to the listening socket will be the address of the local end of the resulting connection.
While I was reading how to make a TCP client/server connection in C, I had a doubt about the bind() function.
I read that you need this function to "bind" a socket you've created to a local IPEndPoint, because the client/server connection takes a socket pair, made by LocalIP:LocalPort, RemoteIP:RemotePort. Thus my questions are:
What happens and what does the kernel do when a client doesn't call bind(), but calls connect() immediately after creating a socket (this is a common thing; I do it too in a client program, but I don't understand why I needn't to bind)?
... and above all ...
Why does a server program call bind(), specifying INADDR_ANY as the LocalIP address? I read that this constant is useful to specify a generic IP address, that is the server accepts data from anywhere on the Internet. But... is this a specification of a local IP address, or does it indicates where the clients can reach the server? I'm getting very confused...
1) You usually only need to call Bind if you want to create a server socket. There are some cases where it is required to establish a client socket, but more often than not, it is not necessary for for a client sockets. If you want to wait for incoming connections on a certain port, you have to bind to it. If you want to connect out to some IP and Port, there's no need to bind. The server socket's bind takes exclusive access to the TCP port. Nothing else can come online and bind to that port until your application closes or the socket is closed by you.
2) You are specifying which IP on the local computer to bind to. A single computer can have many IP addresses. Your computer may have a wired and wireless connection. Each has its own IP on the local network. You can specifically bind to one of those IPs and not the other. You could even have one application bound to port 473 (for example) on one IP and an entirely different application bound to port 473 on the other IP. If you specify INADDR_ANY, you are binding to all valid IPs the machine has. So it doesn't matter what IP the client used to get to you, it will work.
What happens and what does the kernel do when a client doesn't call bind(), but calls connect() immediately after creating a socket (this is a common thing; I do it too in a client program, but I don't understand why I needn't to bind)?
When you make an outbound connection without first binding the socket to an IP/port, the kernel will pick a source IP and port automatically, based on routing tables and what ports are available.
Why does a server program call bind(), specifying INADDR_ANY as the LocalIP address? I read that this constant is useful to specify a generic IP address, that is the server accepts data from anywhere on the Internet. But... is this a specification of a local IP address, or does it indicates where the clients can reach the server? I'm getting very confused...
What you've read is inaccurate -- the IP address in the sockaddr passed to bind() doesn't indicate where the server will accept connections from. It indicates what local IP addresses the socket should be attached to. INADDR_ANY indicates that you want to listen for connections on the specified port on any and all IP addresses attached to the machine. On servers with multiple IP addresses, it's often useful to specify one IP address to bind() to, so that other sockets can be bound to the same port on other IPs. It's also often useful to bind to a port on localhost only.
In my own experience,I bind 1 socket and dispatch the requests to other threads.
But the famous web server nginx is bind() multiple sockets on the destination port.
What's the benefit to do it this way?
Looking through nginx source, I don't see that possibility. To quote from the man page ip(7)
When a process wants to receive
new incoming packets or connections,
it should bind a socket to a local
interface address using bind(2). Only
one IP
socket may be bound to any given local (address, port) pair.
So, I think that there is something else going on. Can you mention how you determined that nginx was doing this?