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

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.

Related

What is the POSIX call to determine the intended IP of a redirected socket open request?

I am modifying my hosts file to change the IP address of (for example a database call) to a local proxy that I am writing.
10.1.2.3 localhost
10.1.2.4 localhost
I want the proxy listening on the socket to work out which machine the socket opening request intended to go to. eg in my client I am calling.
dbPort = 4000;
openDatabaseConnection("10.1.2.3", dbPort);
...
openDatabaseConnection("10.1.2.4", dbPort);
So both call on the same socket. I want my proxy server to listen on 4000 and redirect the one going to 10.1.2.3 to the correct server by intended IP address.
Is there a POSIX call to get this from the socket header?
My question is: What is the POSIX call to determine the intended IP of a redirected socket open request?
No there is no way of knowing which IP-address was used in the client program. The hosts-file defines a set of aliases, and the aliases are replaced with the actual address (in your case localhost) by the name/address resolver, making you lose all information about the alias used. There is no "redirection" made, the alias substitution is made before the client even connects.
The simplest way to solve your problem is not to use IP-address aliasing through the hosts file, but to use different port numbers.
You could probably also add "virtual" interfaces for the different addresses, and have the proxy-server listen for connections on both those interfaces.

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.

Setting destination port with TCP socket

In the case where the source port and destination port of a non-blocking TCP socket are not in agreement(for a p2p application), how does one specify the destination port that the socket will Connect() to?
In case of P2P the clients first connect to torrent to get a list of peers(seeders) and the port number which is open at the peer. The system which wants to download will then connect to the peer using the address and port provided by the tracker.
The peers are not restrictive(generally) and accept connections from any source address or ip
Specifying the destination port of a connection is done in the sockadder-struct that you pass to the connect()-call. Since you don't specify which OS you are working on, in it is difficult to provide a concrete example. However, for both Linux and Windows, you would typically load the sockaddr-struct using getaddrinfo(). A nice Linux-example is provided here, while MS has an example in their official documentation.

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.

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

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