How to connect/communicate TCP client with server on another network - c++

I am attempting to create a TCP client/server chat. My goal currently is to switch my client connection from using the local ip address "127.0.0.1" to being able to connect to the server that could possibly be in another computer not in the local network. Essentially if I the client was in Los Angeles, I would like to be able to communicate with the server in San Diego.
I am aware of "port forwarding" and have gone ahead and tried to configure my router. The port that the server is listening to is 8000. The IP address I use in "LAN IP ADDRESS" is the address I obtained from going (on ubuntu) settings->network->IPV4 address: 10.0.2.15.
router settings
Here is the code used in my server.cpp and client.cpp:
// server.cpp
// Attach socket to port:
int option{1};
if(setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &option, sizeof(option)))
{
logE("error in setting socket options");
return EXIT_FAILURE;
}
// INADDR_ANY: bind socket to all local interfaces, using IPV4 family:
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);
if(bind(server_fd, (struct sockaddr*)&address, sizeof(address)))
{
logE("binding socket failed");
return EXIT_FAILURE;
}
//client.cpp
// setup sockets method of connection:
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(PORT);
/* serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); */
/* serverAddr.sin_addr.s_addr = inet_addr("IP 1"); */
serverAddr.sin_addr.s_addr = inet_addr("IP 2");
// Connect to server:
if(connect(server_fd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)))
{
logE("connection to server failed");
return EXIT_FAILURE;
}
In client.cpp "IP 1" is the IP I get when going on https://whatismyipaddress.com/, "IP 2" is the address I use that logs me into my router.
I have not been able to connect to my server using either of the two IP's, furthermore I have attempted to use different IP's in my router settings as well. Also I am aware of "static ip address" which would help the server maintain one constant IP, but I would first like to try using whatever IP address the servers machine is currently using.
Furthermore, My server.cpp is running within my Ubuntu Virtual Machine, which is hosted on Windows. Since I don't have another machine at my disposal I am testing / running this on the same VM currently for testing purposes, but once everything works I will go ahead and as a friend to test different machines.

Related

Can I use the same sockaddr_in in TCP and UDP?

In my serveur, I bind the TCP and UDP on two different ports.
I first connect my Client with TCP (via accept, etc)
Then I want to use UDP to communicate between my server and my client.
So I tried to use the same sockaddr_in like that :
void AUDPMonitor::sendMessage(Message &msg)
{
for (ISocket *socket: *_fdListClients)
{
if (msg.getClientId() == socket->getSock())
{
UDPSocket *UdpSocket = reinterpret_cast<UDPSocket *>(socket);
UdpSocket->send(msg, socket->getUserAddr());
break;
}
}
}
The _fdListClients is a vector of Socket I got from the TCP connexion.
There is no error messages but my client doesn't receive anything.
So I want to know if it's possible to use the same sockaddr_in or if it's impossible.
Edit : When I accept the client socket
socklen_t client_sin_len;
sockaddr_in *client_sin = new sockaddr_in;
client_sin_len = sizeof(sockaddr_in );
std::cout << "New User ! " << std::endl;
if ((cs = accept(fd, reinterpret_cast<struct sockaddr *>(client_sin), &client_sin_len)) == -1)
You can use the same copy of the sockaddr_in for TCP and UDP, but they have to be on different sockets.
A given socket created with AF_INET also specifies either SOCK_STREAM making TCP or SOCK_DGRAM making it UDP.
So if you have this:
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(12345);
You can pass this to bind with a TCP socket to bind to TCP/12345, and you can pass it to bind with a UDP socket to bind to UDP/12345.
you can use the same SOCAKADDR_IN structure for a TCP or UDP server or client but whenever you want to use it for a different one you should change the values of port and address because servers cannot be bound to the same port.
so if we have two remote stations running a TCP server and a UDP Server then the client to connect them:
SOCKET servTcp; // a remote bound and listing tcp socket waiting for remote clients through the blocking function `accept`
SOCKET servUdp; // a remote bound Udp server waiting for clients
// for the client:
SOCKET clientTcp = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
SOCKET clientUdp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
SOCKADDR_IN sa_serv;
sa_serv.sin_addr.S_un.S_addr = inet_addr("127.168.0.1");
sa_serv.sin_family = AF_INET;
sa_serv.sin_port = htons(777);
now the socket clientTcp can connect to the remote tcp server using this address structure.
to use the same SOCKADDR_IN structure sa_serv for the the udp server:
as long as the tpc and the udp servers on the same remote machine we only change the port:
sa_serv.sin_port = htons(1000); // the port is unique for servers to bind on.
now we the udp socket clientUdp can use use sa_serv to send and receive data from the remote udp serv.
SOCKADDR_IN is the same for udp and tcp just change the value of port and sometimes address if server.

How to find the ipaddress of a server which is used for accepting a client in c++?

I have to find the ipaddress of a machine in which my server program is running. Server is listening to all addresses(::0 - ipv6). Now I need to find the ip in which is accepting a client connection. I tried with getsockname(), but it is not working. It gives me an ip 0.0.0.0 even if i am using socket descriptor which accept() returns.
Code snippet:
addr_len = sizeof(addr);
addr.sin_family = AF_INET;
res = getsockname (client, (struct sockaddr *)&addr,(socklen_t*) &addr_len);
inet_ntop(AF_INET, &(addr.sin_addr), ip_str, INET_ADDRSTRLEN);
IPaddr = ip_str;
But if i replace ipv6 address(::0) with ipv4 counterpart(0.0.0.0), This code is working. Can anyone guide me to make this generic and work with both versions of ip address?

Use C++ socket to validate ethernet interface configuration in QNX

I have a program that configures the ethernet interface on a remote machine running a QNX Environment, which uses ifconfig to assign an IP Address, netmask and default gateway. I now need a way to determine whether the ethernet interface has a valid configuration, that I would be able to connect to remotely.
For example, giving "127.0.0.1", "255.255.255.255", or "0.0.0.0" as IP Addresses should be invalidated, because even though they are valid IP Addresses, I would not be able to establish a remote connection with these.
I need a way for a C++ application to verify that the configuration is valid and can be connected to.
I have heard that one way to do this is to try and create a socket, but I haven't had any luck so far. I was able to create a socket with "0.0.0.0" as the IP Address just as easily as a valid one.
Maybe I'm just not doing it right.
int sock = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in ipaddr;
ipaddr.sin_family = AF_INET;
inet_pton(AF_INET, "0.0.0.0", &ipaddr2.sin_addr);
bind(sock2, (struct sockaddr *) &ipaddr2, sizeof(ipaddr2));
Is there anything else I could do with this socket to verify connectivity?
Any help would be greatly appreciated!

weird about send udp packet to local lan

I'm using visual studio 2003 to write a simple program of communcation with local LAN via UDP socket. And I'm trying to not use MFC. The following is a small piece of code I used to test UDP socket:
static void sendMsg(char *buf, int len)
{
SOCKET sock;
struct sockaddr_in addr;
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0)
return;
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = inet_addr("192.168.2.108"); // Specify dest IP
sendto(sock, buf, len, 0, (struct sockaddr*)&addr, sizeof(addr));
closesocket(sock);
}
To verify if the packet is send out, I use wireshark to capture packet.
My PC's IP is 192.168.1.107. The strange is that if dest IP is a local IP like 192.168.1.108, I cannot capture the packet in wireshark. But if the dest IP is 192.168.1.1 (gateway) or 192.168.1.255(broadcast) or outside of LAN ip like 192.168.2.108, I can capture the UDP packet.
Who can explain this for me? Is there any wrong with my code?
If you're sending an UDP packet to an IP address that is not known by your machine, it will ask for the machine's MAC address first via the ARP protocol.
If it gets a response, it will send your packet to the MAC address it receives, if it cannot get a response about the MAC address, the UDP packet won't be sent at all.
192.168.1.1 is an existing machine (the default router) and everything outside your LAN will go through that existing default router, so you will see your UDP packets transmitted. If you try to send to a non existing IP on your LAN, you won't see any packet sent since ARP will fail before your packet is even transmitted.

How do i check the data sent to the IP Address on particular port?

I am sending data to the IP address 127.0.0.1 on port number 5152. Through socket programming i am sending the data ("Hello world") . I am receiving a acknowledgement as sent 51 Bytes. But how do i know the data received is correct or not in the above IP address.
I have created a server application , and i am using a same IP and port number here.
// Create our listening socket
//
sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (sListen == SOCKET_ERROR)
{
printf("socket() failed: %d\n", WSAGetLastError());
return 1;
}
// Select the local interface and bind to it
//
if (bInterface)
{
local.sin_addr.s_addr = inet_addr(szAddress);
if (local.sin_addr.s_addr == INADDR_NONE)
usage();
}
else
local.sin_addr.s_addr = htonl(INADDR_ANY);
local.sin_family = AF_INET;
local.sin_port = htons(iPort);
if (bind(sListen, (struct sockaddr *)&local,
sizeof(local)) == SOCKET_ERROR)
{
printf("bind() failed: %d\n", WSAGetLastError());
return 1;
}
Bind fails with 10048 error.
Depend on what you're connecting to. If it's your application, the fact that the socket opens proves that you already have a listening socket : just display what it receives (or configure the traces on the server to display it).
Another idea when dealing with network development is to monitor actual network traffic using wireshark.
You sent your data - now you need to receive it !
You'll need to create a server that listens on port 5152 on the same box and have it display what it receives from your client.
Your error is "address already in use". That means some other program has the port open.
You can see a list of programs listening using "netstat" at the command line. Perhaps that
will help you figure it out.
Wireshark is a handy application to see what's being sent via the network. Very handy for debugging these kinds of programs.