Simple Windows 10 UDP Broadcast Send and Receive Not Working - c++

I am trying to implement a simple UDP broadcaster and listener on two PCs running Windows 10 64 Pro (1803). I have come across numerous c/c++ examples but I cannot get any of them to work on my local net.
I set up a receiver PC on my local net at 192.168.0.1 and a sender PC at 192.168.0.2 with subnet masks 255.255.255.0 and use the local broadcast address of 192.168.0.255.
They do work when used on the same machine with localhost, MS loopback adapter and any local adapter I might choose. They also work with two machines connected to a wifi router with a gateway. They just don't seem to work with a regular basic switch, which is what I need. I can see the messages coming in on the listener PC using Wireshark but my listener code (recvfrom()) does not respond. If tried disabling the Windows firewall but that has no effect.
*One interesting thing. If I have the listener code up, and send a broadcast from that listener PC, the listener code WILL respond to that and to subsequent broadcasts from the broadcaster PC while in the while loop. If I exit and restart, its the same nonresponsive result as before.*
This code that follows is one of many I have tried but they're all basically the same handful of operations.
Example sender code:
#include <winsock2.h>
#include <iostream>
#include <conio.h>
using namespace std;
#define MYPORT 9009 // the port users will be connecting to
int main()
{
WSADATA wsaData;
WSAStartup( MAKEWORD( 2, 2 ), &wsaData );
SOCKET sock;
sock = socket( AF_INET, SOCK_DGRAM, 0 );
char broadcast = '1';
if ( setsockopt( sock, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast) ) < 0 )
{
cout<<"Error in setting Broadcast option";
closesocket(sock);
return 0;
}
struct sockaddr_in Recv_addr;
struct sockaddr_in Sender_addr;
int len = sizeof( struct sockaddr_in );
char sendMSG[] ="Attention: this is a broadcast!!!";
char recvbuff[50] = "";
int recvbufflen = 50;
Recv_addr.sin_family = AF_INET;
Recv_addr.sin_port = htons( MYPORT );
Recv_addr.sin_addr.s_addr = inet_addr( "192.168.0.255" ); // switch doesnt work
// Recv_addr.sin_addr.s_addr = inet_addr( "192.168.1.255" ); //wifi router works
cout << "sending message: " << sendMSG;
sendto( sock, sendMSG, (int) strlen(sendMSG)+1, 0,(sockaddr*) &Recv_addr, sizeof( Recv_addr ) );
closesocket( sock );
WSACleanup();
}
Example receiver code:
#include "winsock2.h"
#include <iostream>
#include <conio.h>
using namespace std;
#define MYPORT 9009 // the port users will be connecting to
int main()
{
WSADATA wsaData;
WSAStartup( MAKEWORD( 2, 2 ), &wsaData );
SOCKET sock;
sock = socket( AF_INET, SOCK_DGRAM, 0 );
char broadcast = '1';
// This option is needed on the socket in order to be able to receive broadcast messages
// If not set the receiver will not receive broadcast messages in the local network.
if ( setsockopt( sock, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof( broadcast ) ) < 0 )
{
cout<<"Error in setting Broadcast option";
closesocket(sock);
return 0;
}
struct sockaddr_in Recv_addr;
struct sockaddr_in Sender_addr;
int len = sizeof( struct sockaddr_in );
char recvbuff[50];
int recvbufflen = 50;
Recv_addr.sin_family = AF_INET;
Recv_addr.sin_port = htons( MYPORT );
Recv_addr.sin_addr.s_addr = INADDR_ANY;
if ( bind( sock, (sockaddr*) &Recv_addr, sizeof (Recv_addr) ) < 0 )
{
cout << "Error in BINDING" << WSAGetLastError();
_getch();
closesocket(sock);
return 0;
}
do
{
cout << "\nWaiting for message...\n";
recvfrom( sock, recvbuff, recvbufflen, 0, (sockaddr*) &Sender_addr, &len );
cout << "Received Message is: " << recvbuff;
} while ( 1 );
closesocket(sock);
WSACleanup();
}

Related

How can I start both TCP and UDP client in the same function concurrently?

I have a UDP server-client system that works correctly. I want to create a single function that takes in input for both UDP and TCP connection sockets and these connections should be able to take input concurrently. Previously I worked with pthreads in C and I only know how to pass some tasks to specific functions(don't know how to do these tasks concurrently in the same function). Could you please provide a very simple example of a function that can run TCP client and UDP client concurrently?
void UDP(){
int fd;
if ( (fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket failed");
return 1;
}
struct sockaddr_in serveraddr;
memset( &serveraddr, 0, sizeof(serveraddr) );
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons( 50037 );
serveraddr.sin_addr.s_addr = htonl( 0x7f000001 );
for ( int i = 0; i < 4; i++ ) {
if (sendto( fd, "hello", 5, 0, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0 ) {
perror( "sendto failed" );
break;
}
printf( "message sent\n" );
}
close( fd );
}
#include <stdio.h> // Default System Calls
#include <stdlib.h> // Needed for OS X
#include <string.h> // Needed for Strlen
#include <sys/socket.h> // Needed for socket creating and binding
#include <netinet/in.h> // Needed to use struct sockaddr_in
#include <time.h> // To control the timeout mechanism
#include <unistd.h>
#define EXPR_SIZE 1024
#define BUFLEN 512
#define TRUE 1
#define SERVERLEN 1024
int main( void )
{
int fd;
if ( (fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror( "socket failed" );
return 1;
}
struct sockaddr_in serveraddr;
memset( &serveraddr, 0, sizeof(serveraddr) );
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons( 50037 );
serveraddr.sin_addr.s_addr = htonl( INADDR_ANY );
if ( bind(fd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0 ) {
perror( "bind failed" );
return 1;
}
char buffer[200];
for ( int i = 0; i < 4; i++ ) {
int length = recvfrom( fd, buffer, sizeof(buffer) - 1, 0, NULL, 0 );
if ( length < 0 ) {
perror( "recvfrom failed" );
break;
}
buffer[length] = '\0';
printf( "%d bytes: '%s'\n", length, buffer );
}
close( fd );
}

Why am I not able to change my socket from blocking to nonblocking?

When my connect() function calls I get a 10035 connect error after putting my socket into nonbloking mode? My code should work without that error. Anyone tell me why this is happening?
#include <stdio.h>
#include <winsock2.h>
#include <windows.h>
#include <string.h>
#include <iostream>
#include <string>
#include <stdio.h>
#pragma comment(lib,"ws2_32.lib") //Winsock Library
#pragma comment(lib,"ws2_32")
using namespace std;
const int arrsize = 1;
int main(int argc , char **argv)
{
//Declare WSADATA structure containing information about windows sockets implementation.
WSADATA wsa;
//Create a socket object
SOCKET s;
struct sockaddr_in server;
const char *message;
char server_reply[arrsize];
int recv_size;
//Create socket.
cout << "Creating socket for connection." << endl;
if((s = socket(AF_INET , SOCK_STREAM , 0)) == INVALID_SOCKET)
{
printf("Could not create socket : %d" , WSAGetLastError());
}
Right here. Why do I keep getting a error from my connect() function? The error is 10035. I am trying to make my socket nonblocking mode.
u_long mode = 1; //For nonblocking mode.
ioctlsocket(s, FIONBIO, &mode);
char address[100] = "172.217.23.36";
server.sin_addr.s_addr = inet_addr(address);
server.sin_family = AF_INET;
server.sin_port = htons( 80 );
//Establish connection.
if ( connect(s, (struct sockaddr *)&server , sizeof(server)) < 0 )
{
puts("Function connect() did not connect.");
printf ( " %d", WSAGetLastError() );
return 1;
}
message = "GET / HTTP/1.1 \r\n\r\n";
if( send(s , message , strlen(message)+1, 0) < 0)
{
puts("Function send() failed.");
return 1;
}
if ( (recv_size = recv(s , server_reply , arrsize, 0)) == SOCKET_ERROR )
{
puts("Function recv failed.");
return 1;
}
closesocket(s);
//Terminate use of Winsock 2 DLL by calling WSACleanup() function.
WSACleanup();
return 0;
}
So you have an error code. The very first thing to do is read the documentation:
10035: WSAEWOULDBLOCK. Resource temporarily unavailable. This error is returned from operations on nonblocking sockets that cannot be completed immediately,
So the error you have is a direct result of having a non-blocking socket.
You need to use some appropriate wait function and once it signals readiness, then you can finish the connect operation.
https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-connect

UDP respond on connected socket

So I've been programming with TCP for quite a while, and decided to pick up UDP. I'm not quite sure what needs to be done in order for me to have communication both ways across the WAN(or lan for that matter, easier on lan because I could just open two ports) With UDP once I send information from client to server how can I respond on that socket. Is there a way to connect directly?
(Current quick functions)
int udpsock(int port, const char* addr){
int handle = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
if (handle < 1)
return -1;
sockaddr_in address;
address.sin_family = AF_INET;
if (addr == INADDR_ANY)
address.sin_addr.s_addr = INADDR_ANY;
else
address.sin_addr.s_addr = inet_addr(addr);
address.sin_port = htons( (unsigned short) port );
if ( bind( handle, (const sockaddr*) &address, sizeof(sockaddr_in) ) < 0 )
return -1;
return handle;
}
string recvudp(int sock,const int size){
sockaddr_in SenderAddr;
int SenderAddrSize = sizeof (SenderAddr);
char buf[size];
int retsize = recvfrom(sock, buf, sizeof(buf), 0, (SOCKADDR *) & SenderAddr, &Sen derAddrSize);
if (retsize == -1){
cout << "\nRecv Error : " << WSAGetLastError();
if (WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == 0){
return "";
}
return "\0";
}
else if (retsize < size){
buf[retsize] = NULL;
}
return buf;
}
int sendudp(string str, string ip, unsigned short port, int sock){
sockaddr_in dest;
dest.sin_family = AF_INET;
dest.sin_addr.s_addr = inet_addr( ip.c_str() );
dest.sin_port = htons( port );
int ret = sendto(sock,str.c_str(),str.size(),0, (sockaddr*)&dest,sizeof(dest));
if (ret == -1){
cout << "\nSend Error Code : " << WSAGetLastError();
}
return ret;
}
With this it's pretty easy to make a socket with port xxxx and have the partner send on that port to get data to the client, the forth part is where I'm having some trouble =]
Make your sendudp function take a sockaddr_in. You get one back from recvfrom and can pass it to sendto. Alternatively, pass the received sockaddr_in to connect and use send from then on.
I assume that functions you posted should be shared between client and server. They need to be slightly modified in order to achieve that. E.g. on the server side, recvudp should return client address (possibly as an out parameter) as it is needed later for sending message back to it. Furthermore, as client address structure is already filled (in recvudp on the server side or manually on the client side) we can just pass it to sendudp as its argument.
I've played with this a bit and created two simple projects in Visual Studio 2010: UDP Server and client. They both use shared functions mentioned above. This code is far from perfect and is aimed only to show basic UDP socket communication.
Shared.h:
#ifndef SHARED_H
#define SHARED_H
#include <winsock2.h>
#include <string>
int udpsock(int port, const char* addr);
std::string recvudp(int sock, const int size, sockaddr_in& SenderAddr, int& SenderAddrSize);
int sendudp(std::string str, sockaddr_in dest, int sock);
#endif
Shared.cpp:
#include "Include\shared.h" // path to header - you might use different one
#include <iostream>
using namespace std;
int udpsock(int port, const char* addr)
{
int handle = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
if (handle < 1)
return -1;
sockaddr_in address;
address.sin_family = AF_INET;
if (addr == INADDR_ANY)
address.sin_addr.s_addr = INADDR_ANY;
else
address.sin_addr.s_addr = inet_addr(addr);
address.sin_port = htons( (unsigned short) port );
if ( bind( handle, (const sockaddr*) &address, sizeof(sockaddr_in) ) < 0 )
return -1;
return handle;
}
// function should return sender address info (for the code the server)
string recvudp(int sock, const int size, sockaddr_in& SenderAddr, int& SenderAddrSize)
{
// TODO: use std::vector<char> here instead of char array
char* buf = 0;
buf = new char[size];
int retsize = recvfrom(sock, buf, size, 0, (sockaddr*) &SenderAddr, &SenderAddrSize);
if(retsize == -1)
{
cout << "\nRecv Error : " << WSAGetLastError();
if (WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == 0)
{
return "";
}
return "\0";
}
else if (retsize < size)
{
buf[retsize] = NULL;
}
string str(buf);
delete[] buf;
return str;
}
// On the client side, prepare dest like this:
// sockaddr_in dest;
// dest.sin_family = AF_INET;
// dest.sin_addr.s_addr = inet_addr(ip.c_str());
// dest.sin_port = htons(port);
int sendudp(string str, sockaddr_in dest, int sock)
{
int ret = sendto(sock,str.c_str(),str.size(),0, (sockaddr*)&dest,sizeof(dest));
if (ret == -1)
{
cout << "\nSend Error Code : " << WSAGetLastError();
}
return ret;
}
Server: main.cpp:
#include <winsock2.h>
#include <string.h>
#include <iostream>
#include "..\Shared\Include\shared.h"
// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")
#define SERVER_PORT 27015
#define MAX_MSG 1024
using namespace std;
int main(int argc, char *argv[])
{
WSADATA wsaData;
int nResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if(nResult != NO_ERROR)
{
cout << "WSAStartup failed with error: " << nResult << endl;
return 1;
}
sock = udpsock(SERVER_PORT, "127.0.0.1");
cout << "Waiting for datagram on port: " << SERVER_PORT << endl;
while(1)
{
sockaddr_in clientAddr;
// receive message
int clientAddrLen = sizeof(clientAddr);
cout << "Received message from the client: " << recvudp(sock, MAX_MSG, clientAddr, clientAddrLen) << endl;
sendudp("Hello from server!", clientAddr, sock);
}
WSACleanup();
return 0;
}
Client: main.cpp:
#include <winsock2.h>
#include <iostream>
#include "..\Shared\Include\shared.h"
using namespace std;
#define MAX_MSG 1024
// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")
int main(int argc, char* argv[])
{
WSADATA wsaData;
int nResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (nResult != NO_ERROR)
{
cout << "WSAStartup failed with error: " << nResult << endl;
return 1;
}
SOCKET sock = INVALID_SOCKET;
// Create a socket for sending data - it does not need to be binded like listening socket!
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(sock == INVALID_SOCKET)
{
cout << socket failed with error: " << WSAGetLastError() << endl;
WSACleanup();
return 1;
}
unsigned short Port = 27015;
sockaddr_in dest;
dest.sin_family = AF_INET;
dest.sin_addr.s_addr = inet_addr("127.0.0.1");
dest.sin_port = htons(Port);
sendudp("Hello from client!", dest, sock);
sockaddr_in RecvAddr;
int recvaddrlen = sizeof(RecvAddr);
cout << "Received message from the server: " << recvudp(sock, MAX_MSG, RecvAddr, recvaddrlen) << endl;
cout << "Closing socket..." << endl;
nResult = closesocket(sock);
if(nResult == SOCKET_ERROR)
{
cout << "closesocket failed with error: " << WSAGetLastError() << endl;
WSACleanup();
return 1;
}
WSACleanup();
return 0;
}
If you run client twice output is:
Server:
Waiting for datagram on port: 27015
Received message from the client: Hello from client!
Received message from the client: Hello from client!
Client:
Received message from the server: Hello from server!
Closing socket...
UDP is connectionless protocol, server just needs to start listening on UDP port and client can send data (datagram) immediately, there is no need for connection establishment (e.g. with connect()/accept(), like in TCP).

C++ problem with Datagram (UDP)winsocket to sendto and recvfrom on the same socket through the loopback adapter

I am trying to send some data with a udp socket and receive them back on the same socket through windows loopback adatper. In my network properties I set the loopback adapter to have the following ip 192.168.1.1
the recvfrom function returns -1 indicating an error. I also monitor the traffic on the loopback adapter with wireshark and nothing seem to be sent to the loopback adapter, I see no trafic.
Is it true that on windows we can't use the loopback address(127.0.0.1) ? I saw that on some forums, that is why I try to use the loopback adapter.
I also tried to send directly to my own ip, but it gives no better results. Btw it is possible to send to his own ip and get the data back?
I would appreciate any help and just in case, I am new to socket programming.
Below is my code:
#define DST "192.168.1.1"
int _tmain(int argc, char* argv[])
{
int numbytes;
int bytes_sent;
int server_sock;
char send_msg[100];
int send_msg_length = 100;
char rcv_msg[100] = { 0 };
int rcv_msg_length = 100;
int i;
WSADATA wsaData;
if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
fprintf(stderr, "WSAStartup failed.\n");
return 1;
}
sockaddr_in to_addr;
sockaddr_in me;
unsigned short Port = 27015;
to_addr.sin_family = AF_INET;
to_addr.sin_port = htons(Port);
to_addr.sin_addr.s_addr = inet_addr(DST);
me.sin_family = AF_INET;
me.sin_port = 0;
me.sin_addr.s_addr = htonl(INADDR_ANY);
memset( &(me.sin_zero), '\0', 8 );
if ((server_sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
perror("talker: socket");
}
if ( bind( server_sock, (SOCKADDR *)&me, sizeof( me ) ) == -1)
{
printf("Error binding/n");
return 1;
};
int length = sizeof( to_addr );
bytes_sent = sendto(server_sock, send_msg, send_msg_length, 0, (SOCKADDR *)&to_addr, length);
if (bytes_sent == -1)
{
perror("talker: sendto");
exit(1);
}
printf("Sent %d bytes to %s\n", bytes_sent, DST);
printf("listener: waiting to recvfrom...\n");
if ( numbytes = recvfrom(server_sock, rcv_msg, rcv_msg_length, 0, (SOCKADDR *)&to_addr, &length ) )
{
perror("recvfrom");
exit(1);
}
closesocket(server_sock);
WSACleanup();
return 0;
}
You are binding your server socket to port 0, i.e. asking the OS to assign random port number to it. That has to be the same port you are sending to, 27015 in your case.
Also, you don't have to byte-swap INADDR_ANY.

How to set up a socket for UDP multicast with 2 network cards present?

I'm trying to get udp multicast data using sockets and c++ (c). I have a server with 2 network cards so I need to bind socket to specific interface. Currently I'm testing on another server that has only one network card.
When I use INADDR_ANY I can see the udp data, when I bind to specific interface I don't see any data. Function inet_addr is not failing (I removed checking for return value for now).
Code is below.
On a server with one network card, my IP address is 10.81.128.44. I receive data when I run as:
./client 225.0.0.37 12346
This gives me no data:
./client 225.0.0.37 12346 10.81.128.44
Any suggestions? (Hope the code compiles, I removed comments ...)
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
#define HELLO_PORT 12345
#define HELLO_GROUP "225.0.0.37"
#define MSGBUFSIZE 256
int main(int argc, char *argv[])
{
string source_iface;
string group(HELLO_GROUP);
int port(HELLO_PORT);
if (!(argc < 2)) group = argv[1];
if (!(argc < 3)) port = atoi(argv[2]);
if (!(argc < 4)) source_iface = argv[3];
cout << "group: " << group << " port: " << port << " source_iface: " << source_iface << endl;
int fd;
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("socket");
exit(1);
}
u_int yes = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0)
{
perror("Reusing ADDR failed");
exit(1);
}
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = (source_iface.empty() ? htonl(INADDR_ANY) : inet_addr(source_iface.c_str()));
if (bind(fd,(struct sockaddr *)&addr, sizeof(addr)) < 0)
{
perror("bind");
exit(1);
}
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr(group.c_str());
mreq.imr_interface.s_addr = (source_iface.empty() ? htonl(INADDR_ANY) : inet_addr(source_iface.c_str()));
if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
{
perror("setsockopt");
exit(1);
}
socklen_t addrlen;
int nbytes;
char msgbuf[MSGBUFSIZE];
while (1)
{
memset(&msgbuf, 0, MSGBUFSIZE);
addrlen = sizeof(addr);
if ((nbytes = recvfrom(fd, msgbuf, MSGBUFSIZE, 0, (struct sockaddr *)&addr, &addrlen)) < 0)
{
perror("recvfrom");
exit(1);
}
cout.write(msgbuf, nbytes);
cout.flush();
}
return 0;
}
Thanks in advance ...
After some searching and testing I found out here that when binding udp multicast socket we specify port and leave address empty e.g. specify INADDR_ANY.
So the following
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = (source_iface.empty() ?
htonl(INADDR_ANY) :
inet_addr(source_iface.c_str()));
should be look like:
COMMENT: If I understand your code you
should be binding to your multicast
address not the wildcard address. If
you bind to the wildcard address you
will be able to receive unicast
packets on your multicast port.
Binding to your multicast address will
prevent this and ensure you only get
multicast packets on that port.
EDIT: Fixed the code based on above comment, binding to multicast address,
stored in 'group', as opposed to
INADDR_ANY to receive only multicast packets sent to
multicast address.
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = (group.empty() ?
htonl(INADDR_ANY) :
inet_addr(group.c_str()));
This solved the problem. Adding IP_MULTICAST_IF will not help because that is for selecting specific interface for sending udp data, the problem above was on receiving side.
I think you need to add IP_MULTICAST_IF
struct ip_mreq multi;
multi.imr_multiaddr.s_addr = inet_addr(group.c_str());
multi.imr_interface.s_addr = (source_iface.empty() ?
htonl(INADDR_ANY): inet_addr(source_iface.c_str()));
status = setsockopt(me->ns_fd, IPPROTO_IP, IP_MULTICAST_IF,
(char *)&multi.imr_interface.s_addr,
sizeof(multi.imr_interface.s_addr));
I hope that helps.