In C, I can bind a client socket to a specific local address and a system-selected port. What would happen if any of the following happened?
The local address of the machine is changed
The program is moved to a host with a different local address
And what would happen if I attempt to bind after calling connect()?
Well, in general, a TCP socket connection is really identified by the source IP, source port, destination ip, destination port tuple. If say the source IP is not valid any more then neither end can recover from it and the destination host will not probably notice until after a timeout.
If on the other hand you're trying to bind to an address that is not local at that time, the bind system call should return an error (EADDRNOTAVAIL).
Finally, rebinding a connected TCP socket should result in an error because it doesn't make any sense.
Related
Does the bind() function in linux can modify its argument ? I ask this because a sin_port of 0 means that the OS will choose the port, and I would like to get this port after this call.
No, it does not modify the argument. Instead you use getsockname after binding to find out what port you got.
You can also use getsockname after connect to get both the local port assignment and the local address (if you have more than one address) correspomnding to the route to the remote host. This works even with UDP where connect doesn't actually send any packets and only logically binds addresses.
Note: the question was edited.
I have few questions on Berkeley Socket Programming:
Is it possible to change a socket address after binding? If so- What are the C commands to do so?
2.According to https://www.cs.cmu.edu/~srini/15-441/F01.full/www/assignments/P2/htmlsim_split/node18.html, when a socket is bind to INADDR_ANY, it receives packets from all interfaces, but when a packet is sent,(using sent command) it sends through a single NIC with the default IP.
If I understand correctly- if a server has two active NICs, with different IPs, then a socket with the INADDR_ANY parameter can receive a packet with dst IP=x and send a packet with src IP=y, where x is not y. This can cause problems, for example in TCP connections, where the socket in the other destination is will receive the packet, but will drop it due as the dest IP is not the one expected.
Is it true? And if so- does it means that server programs are NOT using INADDR_ANY where there are (two or more) active NICs with different IPs?
Suppose the NIC of the default IP causes bottleneck. Can we change the socket options so that the packets will be send through another NICs(and not the previous NIC)? Can we do so if the NICs have the default IP address?
Can we send packets through one NIC, and set the IP destination to another NIC? (I.e, NIC1 will only send packets, and NIC2 will only receive packets )
Is it possible to change a socket address after created?
Sockets don't have an IP address to change when created. They get one when bound.
If so- What are the C commands to do so?
The Berkeley Sockets API functions to do so are bind() and connect().
When a socket is bind to INADDR_ANY, it receives packets from all interfaces, but sends through a single NIC with the default IP.
No. It sends packets via whichever NIC is necessary to reach the target in each case.
Your cited source draws a distinction without a difference. A socket bound to INADDR_ANY receives packets from any interface. There is no difference between 'any' and 'all' as far as INADDR_ANY is concerned. It is far easier to understand as 'any'.
If I understand correctly- if a server has two active NICs, with different IPs, then a socket with the INADDR_ANY parameter can receive a packet with dst IP=x and send a packet with src IP=y, where x is not y
No. It sends the packet with the same source address the client originally connected to. That's part of what defines the connection.
This can cause problems, for example in TCP connections, where the socket in the other destination is will receive the packet, but will drop it due as the dest IP is not the one expected.
No. The destination in the packet is the client's IP address. Otherwise it wouldn't even get there. This is just nonsense. If you mean the source IP, see above.
Is it true?
No.
And if so- does it means that server programs are NOT using INADDR_ANY where there are (two or more) active NICs with different IPs?
No. INADDR_ANY means exactly what it says. Any IP address: any NIC.
Suppose the NIC of the default IP causes bottleneck. Can we change the socket options so that the packets will be send through another NICs (and not the previous NIC)?
No, but you can alter the IP routing tables.
Can we do so if the NICs have the default IP address?
Only one of them can have the default IP address. The question doesn't make sense.
Can we send packets through one NIC, and set the destination to another NIC?
Only if you're sending to yourself. Otherwise the question doesn't make sense.
(from your citation) When sending, a socket bound with INADDR_ANY binds to the default IP address, which is that of the lowest-numbered interface
I hope this refers to whatever simulator is being described. If it is meant to be a description of how TCP works it is wrong.
When I create a socket, and bind it to a port, it will tell me that the socket is listening on the assigned port. For example,
Create socket.
Bind to port 7006
However, when I connect to another location, the port number appears to change from the outside only. As in, everything works as it should, it just looks like the port is different, and I want to know why.
A server program that took a connection from this socket, bound to 7006, said the address was
localhost:42566
A SOCK_DGRAM socket I made and bound to port 7008 read this address from recvfrom
localhost:a3fs-fileserver
I figure the a3fs-fileserver is just interpreted that way because it happened to have the port typically associated with a3fs-fileserver and getnameinfo tries to get and english service name when possible.
But why does it look different outside my program than inside? Note: This behavior works the same way between machines as well, I just happened to be testing on one for convenience.
Currently, this is my predicament.
I have 2 fd's : x and y. When a write(x) happens, it must go to x-tunnel and a write(y) should go to y-tunnel. I cannot create a routing rule for each connection (Reasons not mentioned here)
Is there a sock opt which I can set when I accept a connection or is there any other way to do it?
Thanks
you can control in sock binding on specific interface for x, y tunnels
check for SO_DONTROUTE option in setsockopt
Your description is sketchy, I think setsockopt() by optname of SO_REUSEADDR and SO_REUSEPORT may help you, but I'm not sure.It can't 'indicate' which interface the packets go to,but you can indicate them by your implement.
Here some reference on Unix Network Programming, if you want to know more detail,you can read them and examples in chapter7.5.
The SO_REUSEADDR socket option serves four different purposes:
SO_REUSEADDR allows a listening server to start and bind its well-known port,
even if previously established connections exist that use this port as their local
port.
SO_REUSEADDR allows a new server to be started on the same port as an
existing server that is bound to the wildcard address, as long as each instance
binds a different local IP address.
SO_REUSEADDR allows a single process to bind the same port to multiple
sockets, as long as each bind specifies a different local IP address.
SO_REUSEADDR allows completely duplicate bindings: a bind of an IP address
and port, when that same IP address and port are already bound to another
socket, if the transport protocol supports it. Normally this feature is supported
only for UDP sockets.
I need to create a program that will communicate with other programs on the same computer via UDP sockets. It will read commands from stdin, and some of this commands will make it to send/receive packets without halting execution. I've read some information out there, but since I'm not familiar with socket programming and need to get this done quickly, I have the following questions:
I need to get a random unused port for the program to listen to, and reserve it so other programs can communicate with this and also the port isn't reserved by another program. I also need to store the port number on a variable for future usage.
Since the communication is across processes on the same machine, I'm wondering if I can use PF_LOCAL.
Also a code sample of the setup of such socket would be welcome, as well as an example of sending/receiving character strings.
Call bind() specifying port 0. That will allow the OS to pick an unused port. You can then use getsockname() to retreive the chosen port.
Answer by Remy Lebeau is good if you need a temporary port. It is not so good if you need a persistent reserved port because other software also uses the same method to get a port (including OS TCP stack that needs a new temporary port for each connection).
So the following might happen:
You call bind with 0 and getsockname() to get a port;
then save it into config (or into several configs) for future uses;
software that needs this port starts and binds the port.
Then you need to e.g. restart the software:
software stops and unbinds the port: the port can now be returned by bind(0) and getsockname() again;
e.g. TCP stack needs a port and binds your port;
software can't start because port is already bound.
So for "future uses" you need a port that is not in ephemeral port range (that's the range from which bind(host, 0) returns a port).
My solution for this issue is the port-for command-line utility.
If it being a random port is actually important, you should do something like:
srand(time(NULL));
rand() % NUM_PORTS; // NUM_PORTS isn't a system #define
Then specify that port in bind. If it fails, pick a new one (no need to re-seed the random generator. If the random port isn't important, look at Remy Lebeau's answer.