Boost-asio listening to multiple IP Addresses on a single (TCP) acceptor - c++

A boost TCP acceptor can be wired up by using an endpoint constructor that only takes a port number as it's argument, in which case it will listen to all IP addresses/NIC's.
Is it possible to get the acceptor to listen to select IP addresses ? Or will I have to create an acceptor for each IP address I am interested in ? Looking through the documentation I couldn't find any indications of this being a possibility.
I haven't looked at the socket API for a few years, but I guess the API doesn't directly allow this.

there's unbound listening and bound one. unbound means you listen to all NICs, bound - to specific one. There's no possibility to select some of NICs, I think because the same can be achived by dedicated acceptors for each of them

Related

Can I call bind() and then connect() on same socket descriptor?

Just a curious question about networking socket programming in a Windows Application with C/C++:
How can I tell the connect() function to use a particular source IP and source port values?
After a socket is created, application calls connect() to remote IP and port by using the sockaddr structure.
the connect() function internally selects the source IP and port for the connection.
Rather than the system deciding the source IP and/or port for the connect(), let that be the application's responsibility to decide which source IP and/or port to bind to.
bind() requests port that is not in use so it can claim it and become a server, while connect() wants a port that is already in use, so it can connect to it and talk to the server.
As user stark said, you need to call bind if you want to specify which interface/port combination to use, although if you want next call to bind it to a random available port number, you can opt out from bind() call because client doesn't necessarily has to have a fixed port number.
It is possible to ask the kernel to select a specific port before calling connect(), but if I may ask - why you wouldn't want to kernel to allocate source ports, as far as I know it's not best practice.
How can I tell the connect() function to use a particular source IP and source port values?
Use the socket library's bind() function for that. Yes, you can call bind() before connect() for an outgoing socket. That is a perfectly legitimate operation for both UDP and TCP sockets.
Yes, you can. Indeed there's a reason to do that: In case your routing policy makes your connection to be established from an IP address which is not the one you want to use, you can force in a multihomed/routing host a specific IP address as source by means of bind(2) system call. Another use is to specify a fixed source port for the connection, but this is not as usual as the previous case.
But beware: you can select only one of the already configured IP addresses you have, not any address you can imagine.

How can two processes which bind on the same port receive the same message?

I have two processes. both listen to the same port.
This is UDP multicast so both use the socket option SO_REUSEADDR, and join the multicast group prior to bind().
When I send a message to the multicast group ip:port only one of the processes gets the message.
How can both of them get it?
Thanks.
Two process can listen at the same port. Although two sockets for connections can't be bound to the same IP address with same port.
You just add an entry for each process in your hosts file that points to a unique ip address.
Something like :
You bind process P1 to 127.0.0.1 port 8080 and P2 to 127.0.0.2 port 8080.
I don't think it's possible, and I think that sometimes it is a lot more coherent this way.
Maybe you should implement a receiver (which will listen to the port) which will distribute the messages to the other processes via inter-processes communication (pipes for instance).

Assign port number manually for each connection

I'm running a server (say on port 50000). Any new request is accepted and a random port is assigned by OS each time. I want to manually assign the port number instead of system doing it randomly for me.
The main reason for this is I'm trying to do some multicast thing based on port number. I'm planning to assign few clients on same port. Next slot of clients on another port and so on.
Any idea?
A TCP socket is identified by a tuple of client-side IP/Port and server-side IP/Port pairs. The server-side IP/Port is decided by calling bind() before listen(). The client IP/Port is decided explicitly by calling bind() before connect(), or implicitly by omitting bind() and letting connect() decide. When a connection is accepted by accept(), it is assigned the client-side IP/Port that made it and the server-side IP/Port that accepted it.
The only random option available here is on the client side. It can call connect() without a preceding bind(), or it can call bind() with a zero IP/Port. In either case, the OS chooses an appropriate network adapter and assigns its IP if not explicitly stated, and assigns a random available ephemeral port if not explicitly stated. Calling bind() allows the client to assign either/both of those values if desired. bind() is not typically used on the client side in most situations, but it is allowed when needed when dealing with specific protocol requirements or firewall/router issues.
Tracking clients by Port alone is not good enough. You need to track the full tuple instead, or at least the client-side IP/port pair of the tuple. Clients from the same network would be using the same client IP but different Ports, but clients from different networks would be using different client IPs and could be using the same client Port, and that is perfectly OK. So using Port alone may find the wrong client from the wrong network. You need to take the client IP into account as well.
When the server accepts a connection, the server has no control over changing the values of the tuple. The OS needs the values to be predictable so it can route packets correctly. When you want to send a packet to a specific client, you need to know both client IP and Port.
If you want to have different server-side IP/Port values in the tuples of accepted connections, the only option is to open multiple listening sockets that are bound with the desired server-side values.

How do I check if a TCP port is already being listened on?

I have a third party library that acts as a HTTP server. I pass it an address and port, which it then uses to listen for incoming connections. This library listens in such a way that it doesn't receive exclusive usage of the port and address it's bound to. As a result, I can listen on the same port multiple times.
I need to run multiple instances of this HTTP server in the same process. Each instance has a default port, but if that port isn't available, it should use the next available port. This is where my problem is; I can end up with two HTTP servers listening on the same port.
I cannot change the HTTP server's code and the HTTP server will not alert me if it cannot listen on the port I give it, so I have to be able to check if a port is already in use before starting each HTTP server. I have tried checking if a port is already being listened on by binding my own socket with SO_REUSEADDR set to FALSE and SO_EXCLUSIVEADDRUSE set to TRUE, but the bind and listen calls both succeed when an existing HTTP server is already listening on that port.
How is this HTTP server achieving this effect, and how can I accurately check if a port is being listened on in this manner?
The quick and dirty method would be to try to connect() to the port on localhost. If the connect() call succeeds, then you know the port is currently being listened on (by whomever received the connection). If the connect call fails (in particular with ECONNREFUSED) then you can be pretty sure that nobody is listening on that port.
Of course, there's a race condition here: Nothing is really stopping another program from swooping in and grabbing the port immediately after you ran the above test, but before you get around to binding to the port yourself. So you should take the result of the test as more of a hint than an absolute rule, and (hopefully) have some way of handling it if you later find out that the port is in use after all.
Use a port number of 0. The OS will pick a free port.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms740621(v=vs.85).aspx explains how the different options interact.
You haven't given us nearly enough information to tell us exactly what's going on in your use case, but I can work through one arbitrary use case that would look like what you're seeing.
Let's say you're on Win 2003 or later, and your primary NIC is 10.0.0.1, and everything is running under the same user account.
The first instance of your app comes up, and your test code tries to bind 10.0.0.1:12345 with SO_EXCLUSIVEADDREUSE. Of course this works.
You close the socket, then tell the HTTP server to listen to port 12345. It binds 0.0.0.0:12345 with SO_REUSEADDR, which of course works.
Now a second instance of your app comes up, and your test code tries to bind 10.0.0.1:12345 with SO_EXCLUSIVEADDREUSE. According to the chart in the MSDN article, that works.
You close the socket, then tell the HTTP server to listen to port 12345. It binds 0.0.0.0:12345 with SO_REUSEADDR, which works.
If this is the problem, assuming you can't get the HTTP server to bind a specific address, you can solve things by using 0.0.0.0 in your test code. (Of course if it's one of the other hundreds of possible problems, that solution won't work.)
If you don't know what socket options, address, etc. the HTTP server is using, and don't have the source, just run it in the debugger and breakpoint the relevant calls.

Is it possible to bind and listen to one IP address with TCP/IP sockets? (Linux/C)

I have always used:
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
which means that I will accept connections from any interface. If I replace the INADDR_ANY with “192.168.0.1”. Does this mean I will only accept connections from the IP address of 192.168.0.1, or does it mean I will accept connections from the interface of 192.168.0.1 resides on?
I have a situation now where I have multiple clients (each with a unique IP address but same port number), trying to connect to one server. Can I have multiple listens functions (separate threads) listening to a unique IP address and port? Or do I have to accept any connection and get the network information after I've connected?
Edit To give more clarification.
If I say serv_addr.sin_addr.s_addr = inet_addr("192.168.0.1") and a client with IP address 192.168.0.2 tries to connect, will the listen command reject this?
The bind address is the local address to listen on; you can specify the address of a local interface.
If you want to control who can connect, you can either inspect the peer address inside the select/accept loop, or limit inbound connections using iptables.
Update
If I say serv_addr.sin_addr.s_addr = inet_addr("192.168.0.1") and a
client with IP address 192.168.0.2 tries to connect, will the listen
command reject this? I want to be able to have multiple thread, each
servicing a unique IP address.
No, the address is an address on a local machine. Given that you're going for a multi-threaded design, I'd recommend you run the listen/accept code in one thread, check the client address, decide what worker thread is appropriate, and then spawn it.
At the risk of showing my age, I still prefer using listen/accept/select for most socket code - it's a personal taste thing, and yes, does influence the design when it comes to blocking/non-blocking IO, buffering, etc.
If I replace the INADDR_ANY with “192.168.0.1”. Does this mean I will
only accept connections from the IP address of 192.168.0.1, or does it
mean I will accept connections from the interface of 192.168.0.1
resides on?
Yes
I have a situation now where I have multiple clients (each with a
unique IP address but same port number), trying to connect to one
server. Can I have multiple listens functions (separate threads)
listening to a unique IP address and port? Or do I have to accept any
connection and get the network information after I've connected?
Yes. You can "fork" (i.e. create a new thread) for each connection you wish to process, however you'd have to do the filtering yourself. There is no way (that I know off in the API) to offload that work to the stack.