Manage 2 Internet Connections? - c++

I have a Linux computer with 2 Ethernet adapters. I also have 2 ADSL models and 2 internet connections. I connect modem A to Ethernet port A and modem B to Ethernet port B.
Now, how to do the following (preferably in C++):
a) Get the IP of each adapter
b) Select the connection to use for downloading (I want to say: download this file with connection A and this with B)
The IPs are dynamic. I am doing this, because my IP must be know to a remote server.
The server must:
a) get the IP
b) send files to this IP
The idea is, every time my IP changes, I will send the new IP to the server, so the server will know where to send the files.
I am using 2 internet connections for:
a) redundancy reasons (if one internet connection is down, I got the second)
b) have faster download speed by opening 2 connections with the server.

If your goal is to simply update a server of your IP address, then you just need to make a connection to this server using a typical TCP socket:
int sock = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in addrLocal = {};
result = connect(sock, (sockaddr*)&server_address, sizeof(server_address));
send(sock, "I have a new IP address", ...);
In the above example, you don't even have to call bind on the socket, as the client TCP/IP stack will consult your computer's routing table for the best local IP address to use (and will pick a random local port).
The client need not even know the IP address it is connecting from nor does it need to tell the server via the socket protocol.. The server in turn can automatically detect your IP address when it does the corresponding accept call when it receives the client connection.
sockaddr_in addrRemote = {};
socklen_t addrRemoteSize = sizeof(addrRemote);
int sockclient = accept(listensocket, (sockaddr*)&addrRemote, &addrRemoteSize);
// the IP address of the client making the connection is in addrRemote.
And if your client just keeps the socket to the server open, then the server can transmit a file back to the client without having to establish a new connection or keep track of any IP address.
Now to answer your original questions, in case you do have a legitimate need to do ascertain a local IP address.
Question 1:
To get the local IP address of each adapter, you can call getifaddrs . From the result list returned from this function, filter out any address that isn't IP, is not UP, or is LOOPBACK.
Question 2:
To bind a socket to a specific adapter, bind to the IP address of the local adapter prior to making a connect call. Example below
...
result = bind(sock, (sockaddr*)&addr, sizeof(addr));
if (result != -1)
connect(sock, (sockaddr_in*)&remoteServer, sizeof(remoteServer));
Where "addr" in the code sample above points to one of the ifa_addr values in the ifaddr array returned by getifaddrs.
Now if there is a NAT involved in any of these connections, then your locally enumerated IP address will be different than the public IP address that the server sees you at.
If you are using UDP sockets, then all of the stuff above still applies, with some tweaks. (e.g. don't call connect(), just call sendto() ).

Related

Can a tcp client use the same port to a different Server?

I want to write a tcp server and client application, which has several different connections to each other where the client uses the same port number.
So far I understand it, the server has a listener port and when the client calls it, then I get a new socket for this new connection on the server side, when I call
accept();
Right? So on Server side I can identify my connection with this new socket and send data through it.
Now my understanding problem with the client side. There I get my socket when I call
socket(AF_INET, SOCK_STREAM, 0)
so I have only one socket. In the
connect()
I can specify remote adress and so on. So when I understand it correctly I can use one socket to make several connects to different adresses/port pairs to create different connections. Right?
But how can I now see in the Client from which logical connection I receive my data or how can I send it when 2 logical connections use the same local port at the client? On serverside I have 2 sockets when I have 2 accept called but what about the client side? For send and receive I have only one socket handle?
Or do I have to call socket() for each logical connection on the client?
I can specify remote adress and so on. So when I understand it correctly I can use one socket to make several connects to different adresses/port pairs to create different connections. Right?
No. A socket is the combination of IP address plus port number.
Or do I have to call socket() for each logical connection on the client?
Yes.
It seems to me your confusion arises because you think for example that a certain port is used for SMTP connections and a certain port is used for HTTP connections.
Well, that port alone is NOT defining for you a socket to the server. The IP address of the server is changing.
As an example, consider the following scenario:
You want to connection to Stackoverflow:
Your PC – IP1+port 50500 ——– Stackoverflow IP2 + port 80 (standard http port)
That is the combination IP1+50500 = the socket on the client computer and IP2 + port 80 = destination socket on the Stackoverflow server.
Now you want to connect to gnu.org:
your PC – IP1+port 50501 ——–gnu.org IP3 +port 80 (standard http port)
The combination IP1+50501 = the socket on the client computer and IP3 + port 80 = destination socket on the gnu.org server.
Better check out Beej's Network Programming to learn more. It is a must-read for anyone working with sockets.
So when I understand it correctly I can use one socket to make several connects to different adresses/port pairs to create different connections. Right?
No. A TCP socket can only be used once. When its connection has finished, or even if connect() just fails to make a connection, you must close the socket and create a new one if you want to make a new connection.
But how can I now see in the Client from which logical connection I receive my data or how can I send it when 2 logical connections use the same local port at the client?
Every TCP connection will have its own unique socket allocated for it. It is your responsibility to keep track of them.
On serverside I have 2 sockets when I have 2 accept called but what about the client side?
The exact same thing happens on the client side, too. You need to create and connect a separate socket for every TCP connection you make. So, you will have a new pair of socket()/connect() calls for every connection.
For send and receive I have only one socket handle?
No, you will have a separate socket for each connection, just like on the server side.
Or do I have to call socket() for each logical connection on the client?
Yes, and connect(), too.
I will not talk about a specific programming language rather I will give a general answer that is applicable for all:
In networking what you care about is the socket (IP+Port) this should be unique whether it is server/client socket or UDP/TCP socket.
For server sockets you must assign a port. For client sockets usually you do not specifically assign a port but it will be assigned by the operating system automatically. However, you can still assign a port to a client socket manually (e.g. in case some port numbers are blocked by the firewall)
In the server process:
you can get the server socket info and the connected client socket info
In the client process:
you can get the client socket info and the server (you want to connect to) socket info (of course you should know the server socket info previously otherwise how will you connect to it).
You can send/receive from/to client sockets. After the server gets the connected client socket it can send/receive through it. Same for the client side it can send/receive through its socket.
The "socket" abstraction is an unfortunate relic of past network stack design. It mixes two different sorts of objects.
A listening socket on the server has a port, and potentially an IP address of the local interface. However, this can also be 0.0.0.0 when listening on all interfaces.
A connected socket is associated with a TCP connection, and therefore has 4 parameters: {local IP, local port, remote IP, remote port}.
Now on the client side, you typically don't care about local IP or local port, so these are locally assigned on connect. And yes, these local parameters can in fact be reused for multiple connections. Only the 4-tuple of {local IP, local port, remote IP, remote port} needs to be unique. The OS will map that unique tuple to your SOCKET.
But since you need a new 4-tuple for every connection, it also follows you need a new SOCKET on both sides, for every connection, on both client and server.

Remote address of active UDP connections in Windows using IP Helper

The function GetUdpTable() in IP Helper returns a table of MIB_UDPROW.
MIB_UDPROW struct does not contain any information about the remote address of the UDP connection, the extended variants of GetUdpTable() only adds the pid to the return struct.
Is it possible to get the remote address for an active UDP connection using IP Helper (or any other winapi)?
No, it is not possible to get the remote port of the UDP connection unless you capture traffic and inspect the packets since UDP is a connectionless protocol.
See: Get Destination Ip/Port of active udp Connection?

How to make a .cpp file to act as an accessible server

I have written a simple program with Linux (Cent OS 7.0) and C++. It is a very small server which sends back a string of characters to the client. But my problem is that I don't know how should I access that server using an IP address?
I have used Linux Socket Interface (Berkeley), and in the section which defines the address, my code does the following:
serverObject.
sin_family = AF_INET;
serverObject.sin_addr.
s_addr = htonl(INADDR_ANY);
serverObject.
sin_port = htonl(portNumber);
I use INADDR_ANY as my server's address which is defined in its definition as:
/* Address to accept any incoming messages. */
Now, how should I run the server, and then use my simple client program to send request to it. My simple client program accepts an IP address as it's destination address, this address should be the one destined toward to the server. How should I relate it then?
INADDR_ANY goes to specify that all active network interfaces in the system should be bound to. So if you're connected to more than one network, you'll be able to communicate with connections coming in from all of them. Most systems will usually have just one, though, and this still goes to say that if the IP bound to that interface happens to change, you'll still bind to that interface.
So, once you specify INADDR_ANY, you need to initiate connections according to the following rules:
If you're connecting from the same physical machine, the easiest thing would be to use the loopback interface (127.0.0.1). However, you can still do (2).
If you're connecting from another machine, you need to pick the accessible IP address of your server from that machine. As said above, if your server is only connected to one network, this will simply be the IP address of the server. Within an internal network this will often be something like 192.168.x.y, or 10.0.x.y—but it doesn't have to.
If you're connecting from a different network which uses a gateway to access your server, then you will need to set up port forwarding in the relevant routers so that when they receive connection to port X, they will know to internally transfer it to your server.
As a server programmer, you decide the port on which to listen, but not the address.
The internet address is provided by your internet provider, or 127.0.0.1 to test on your own machine.
There are plenty of web pages on internet that provide tools to tell you your current public address (search for What is my Ip).
Most of the "home" internet routers implement NAT: they have a single internet address and map them to many device, that carry the Port number to be changed (your port 80 become port (e.g.) 2345 for outside). To allows a client from outside your home to access your server, you are required to configure your router to map the server port, so for example your public port 80 map to your server port 80.
With that said, you should be able to connect your client to your server through an address and port.
If then you want to use a name (example.org) instead of an IP (93.184.216.34), a Domain Name Server is used. But that is another topic.

Mix mode communication between IPv4 and IPv6

I have a application which acts as client and server both. As a server it accepts SOAP requests on port xxxx[Agent URL] and send notifications to the sender on port yyyy [notification URL].
So basically it acts as a server on port xxxx and client on port yyyy. My service has a dedicated IP either IPv6 or IPv4.
We are using GSOAP for communication and overriding GSOAP function tcp_connect() for client side binding.
Currently I am facing issues with transition of service to IPv6. Use case: when I listening on IPv6 address and my notification URL is IPv4...
From the GSOAP implementation a socket is created from the Notification URL.
sk = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
Now we try to bind to this socket accordingly(either IPv4 or IPv6):
struct addrinfo hints, *res, *p;
int status;
const char* client_ip = AGENT_CLIENT_IP;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if( (status=getaddrinfo(client_ip, NULL, &hints, &res))!=0 )
{
sprintf(err_msg_buf,"bind failed in tcp_connect()");
soap->fclosesocket(soap, sk);
return error;
}
for( p=res; p!=NULL; p=p->ai_next){
if(p->ai_family == AF_INET)
{
struct sockaddr_in * ipv4 = (struct sockaddr_in *)p->ai_addr;
status = bind(sk, ipv4, (int)sizeof(struct sockaddr_in));
}
else if(p->ai_family == AF_INET6)
{
struct sockaddr_in6 * ipv6 = (struct sockaddr_in6 *)p->ai_addr;
status = bind(sk, ipv6, (int)sizeof(struct sockaddr_in6));
}
else
{
sprintf(err_msg_buf,"tcp_connect() error. IP Address neither IPv6 nor IPv4 ");
soap->fclosesocket(soap, sk);
return error;
}
break;
}
if(-1 == status)
{
sprintf(err_msg_buf," Binding to client host ip failed in tcp_connect()");
return error;
}
Since the socket is already created(according to the type of Notification URL), bind fails if the socket is of type mismatch is there.
How can I make my client side binding work when socket family and agent ip address are of different family ?
Maybe I am not getting what you are trying or you have some misunderstanding of how TCP/IP and RPC normally works.
Let me paraphrase your set up and then show what I think is odd about it.
You have a server and one or multiple clients. The server accepts IPv4 and IPV6 connections on a fixed port, let us say 1337. To answer the request you open a new TCP stream (or maybe SOAP) on a different fixed port, say 1338. You are now wondering why, when a second client connects the bind to 1338 fails?
The short answer is: "The port is in use, duh, us a different port!"
But that misses the point that the setup, to say the least ODD. Although I have never used GSOAP, I have used SOAP and other RPC frameworks and what you outline is weird, unless I am missing something you did not outline.
The first thing that is odd, if you need an answer to a SOAP request, why do you simply formulate one with a return value? Call the SOAP function and the client will block until it gets an answer. If you don't want the call to block for the relatively long duration of the call do the entire thing asynchronously.
So you want to pass data to the client back later? Here you have two solutions, either the client polls the server or you open a new SOAP connection to the client. The first solution is basically desirable, because in most cases the client can connect to the server but not the other way around. For example the client can be behind a NAT, what do you do now? The second solution works well when you know that the client will always be reachable.
It seems to me that you are trying to do the second "return channel" solution. In this case why are you binding to a port? The client side of any IP connection does not need to bound to a port. The OS will automatically assign an available port. What you need to do is then bind the port on the client to a well known IP. You then use this well known client port and use it in connect on the server (or not, since you are using SOAP).
Since this is all confusing let me illustrate this with a small diagram:
Client Server
------ ------
Request Channel <random port> 1337
Back Channel 1338 <random port>
To sum up:
So either you are reimplementing something that works in SOAP and should stop doing that or if you absolutely need a back channel, simply don't call bind on a client socket.

C++ Sockets with Router

I'm making a multiplayer game using sockets and I have some problems with the server side.The server shall be run from my computer which is behind a router. Therefore I'm a little bit stuck with what should the server inet_addr be. I am using port 1234 and I forwarded it to my PC ( the place where I keep the server ).
I have tried using my own ip address which i got from myipaddress.com, also my computer's router address ( 192.168.0.101 ). The first try i was getting A LOT of connections which ended up in killing the program and in the second try nothing connects to it.
addr.sin_addr.s_addr= inet_addr("192.168.0.101");
addr.sin_port = htons(1234);
addr.sin_family = AF_INET;
What should I do in order to make any client be able to connect to the server and the server to run from behind the router ?
With port forwarding in your router, the router needs to know which device to send packets directed at the selected port range to. The router is asking for your internal IP address, (websites only see your external IP address).
You can find this on Windows by calling ipconfig in cmd (I believe the command may be ifconfig -a on Linux), this lists all of your network interfaces and your internal IP address on any that are connected. You should look for a value in the form 192.168.0.xxx.
When someone then wants to connect to your server if you give them your external IP address and desired port, their packet will be sent to your router on that port, and it will forward it to your computer at the internal IP address.
If you disconnect your computer from the network regularly you may need to configure your internal IP so that it is static and always allocated the same address.
This has nothing to do with your program, and everything to do with your network configuration. Go learn about NAT (network address translation) and doing port forwarding or DMZ on your router.
Usually you want your program to bind to all interfaces - INADDR_ANY - but the important one is the address on the network controlled by your router (often 192.168.0.0/16, but it can be any RFC1918 address block).
Once you have your network configured on your router and binding the external interface from your program (don't hard code an address like in your example, just use INADDR_ANY)
serv_addr.sin_addr.s_addr = inet_addr(INADDR_ANY);