Can I use the same sockaddr_in in TCP and UDP? - c++

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.

Related

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

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.

How to configure Socket to be able to send datagrams via LAN and WLAN?

I wrote an C++ Windows application to send datagrams.
Transferring datagrams are via LAN works as it should.
When I switch to WLAN, no datagrams are transferred.
My understanding is, that the Windows is handling the data transmission, dependent on which connection is established. -> WiFi oder Cable.
My socket configuration is:
WSAStartup(MAKEWORD(2, 2), &m_wsaData);
...
socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
...
setsockopt(m_SendSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&iOptval, sizeof(iOptval));
...
bind(m_SendSocket, (SOCKADDR*)&RecvAddr, sizeof(RecvAddr));
...
How to configure or use other API to be able to send datagrams via LAN and WLAN?
Thank you

ways to send messages to a service?

i had a client server program and i wanted to change the server to a service. so i took some code from here Svp.cpp. it works fine but i created the client server using UDP so i was wondering is there another way to send messages to a service? The client sends messages to the server(service) and the server just echoes them back. is it necessary to have a UDP or TCP connection to send and receive messages?
here is the part of the program that receives the messages from the client (the rest of the code is taken from Svp.cpp)
SOCKET socketS;
InitWinsock();
struct sockaddr_in local;
struct sockaddr_in from;
int fromlen = sizeof(from);
local.sin_family = AF_INET;
local.sin_port = htons(1234);
local.sin_addr.s_addr = INADDR_ANY;
socketS = socket(AF_INET,SOCK_DGRAM,0);
bind(socketS,(sockaddr*)&local,sizeof(local));
while (1)
{
char buffer[1024];
ZeroMemory(buffer, sizeof(buffer));
if (recvfrom(socketS,buffer,sizeof(buffer),0,(sockaddr*)&from,&fromlen)!=SOCKET_ERROR)
{
sendto(socketS, buffer, sizeof(buffer), 0, (sockaddr*)&from, fromlen);
}
}
closesocket(socketS);
If the client and server applications are on the same machine, you could use Named Pipes instead.
Named Pipes
I had a system service that I had to remove the UI, and instead of creating a socket to communicate between the UI and the service, we used Named Pipes. This was nice, because some of our clients were worried about security with an open listening TCP socket on the machine.
If you go this route, you have to set up some sort of signaling between the two applications, because the pipes do not notify you of reads/writes like sockets do. But it is a very workable solution.

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.