Click here to Skip to main content
15,921,905 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am implementing a kind of IP finder for a particular type of some device. I want to find out all the alive devices of that type in the WLAN, with their IP address and other details. The device has its own way of device discovery.

It works as follows: A client sends a broadcast request over the Wireless LAN via UDP. The destination port number is fixed.
In reply, all the devices in the WLAN that understand the format of this request will respond to this request providing information about themselves.

I send the UDP discovery (a broadcast message) by following way :
C++
int iResult = 0;
WSADATA wsaData;

unsigned short Port = 27015;
//-----------------------------------------------
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR) {
        wprintf(L"WSAStartup failed with error %d\n", iResult);
        return 1;
}

// Create a socket
SOCKET sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
	
if (sock == INVALID_SOCKET) 
{
        wprintf(L"socket function failed with error = %d\n", WSAGetLastError() );
}
else 
{
  wprintf(L"socket function succeeded\n");
}

// The socket address to be passed to bind
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr(<my local IP address>);
service.sin_port = htons(Port);

// Bind the socket.
iResult = ::bind(sock, (SOCKADDR *) &service, sizeof (service));
if (iResult == SOCKET_ERROR) 
{
  wprintf(L"bind failed with error %u\n", WSAGetLastError());
  ::closesocket(sock);
   WSACleanup();
  return 1;
}
else
{
  wprintf(L"bind returned success\n");
}
	
char opt = 1;
if(SOCKET_ERROR == setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*)&opt, sizeof(char)))
{
  wprintf(L"setsockopt for SO_BROADCAST failed with error: %u\n", WSAGetLastError());
  closesocket(sock);
  WSACleanup();
  return 1;
}

SOCKADDR_IN brdcastaddr;
memset(&brdcastaddr,0, sizeof(brdcastaddr));
brdcastaddr.sin_family = AF_INET;
bbrdcastaddr.sin_addr.s_addr = inet_addr(<my broadcast IP, i.e. X.X.X.255>); 

int len1 = sizeof(brdcastaddr);
char sbuf[g_iSizeArray] = {'A'B'1','2',0x1,0x0,0x0} ;
    
/* broadcast request */
int ret = ::sendto(sock, sbuf, g_iSizeArray, 0, (sockaddr*)&brdcastaddr, len1);

if(ret < 0)
{
        wprintf(L"Error broadcasting to the clients");
}
else if(ret < int(strlen(sbuf)))
{
   wprintf(L"Not all data broadcasted to the clients");
}
else
{
   wprintf(L"Broadcasting is done");
}

Now my problem is that I can send a broadcast discovery (I see that it on the Wireshark sniffer, and I get responses...) , but I cannot to catch these responses in my app.

As it is written in a similar question here - http://stackoverflow.com/questions/2364574/receiving-responses-from-n-number-of-clients-in-reply-to-a-broadcast-request-o
To catch all responses I tried use the ::select & ::recvfrom methods with same socket and tried to open another one, but it DOES NOT WORK

Any example of solution would be gratefully received!!!
Many thanks in advance.
I am programming in C/C++ in Windows
Posted
Comments
[no name] 21-Aug-14 18:04pm    
Where's the code to receive these replies? Hint: don't use recvfrom since you don't (yet) know the IP/port of the responses.
3iii 24-Aug-14 5:39am    
Firstly thank you bling for your comment
But why you say : "you don't (yet) know the IP/port"?
I know from which port the message will be sent, but you're right the IP I don't know, because it's UDP...(I send the broadcast message on the unknown number of devices)
Maybe you have any example to solve this problem?
[no name] 25-Aug-14 10:56am    
Hi 3-eyes; you have not shown your code for receiving UDP replies. Without that, I cannot comment further. You mentioned "recvfrom". Have you tried using "recv" instead?
3iii 25-Aug-14 11:39am    
Hi bling!
At the moment I'm trying to open a socket to receive any messages, but (!!!) from a specific port....I do it by following way:

SOCKADDR_IN UDPserveraddr;
memset(&UDPserveraddr,0, sizeof(UDPserveraddr));
UDPserveraddr.sin_family = AF_INET;
UDPserveraddr.sin_port = htons(4001);
UDPserveraddr.sin_addr.s_addr = INADDR_ANY;


int len = sizeof(UDPserveraddr);
// Bind the socket.
iResult = ::bind(sockListener, (SOCKADDR*)&UDPserveraddr, sizeof(SOCKADDR_IN));
if (iResult == SOCKET_ERROR) {
wprintf(L"sockListener: bind failed with error %u\n", WSAGetLastError());
::closesocket(sockListener);
WSACleanup();
return 1;
}
else
{
wprintf(L"sockListener: bind returned success\n");
}


//As next step I call the following function
//(it contain code that I show in my question above)
//
SendBroadcast();

//Further there is a cycle where I'm trying to get a message from a few devices ....

while (true)
{
fd_set fds;
struct timeval timeout;
timeout.tv_sec = 50;
timeout.tv_usec = 0;

FD_ZERO(&fds);
FD_SET(sockListener, &fds);
int rc = select(0, &fds, NULL, NULL, &timeout);

if(rc > 0)
{
int buffersize = 340 /*1024*/;
char rbuf[340 /*1024*/];
memset( &rbuf, '\0', buffersize );

SOCKADDR_IN clientaddr;
int len = sizeof(clientaddr);


int nchars = recvfrom(sockListener,rbuf, buffersize, 0,
(sockaddr*)&clientaddr, &len);
if(nchars > 0)
{
char *p = inet_ntoa(clientaddr.sin_addr);
int serverportno = ntohs(clientaddr.sin_port);

//wprintf(L"\r\nBroadcast Server: %s \r\n%s\r\n\r\n", p, rbuf);
printf("Buffer: %s", rbuf);
struct sockaddr_in *si_other_in =
(struct sockaddr_in *)&clientaddr;
std::cout << "\nPkg arrived: "
<< nchars << " "
<< inet_ntoa(si_other_in->sin_addr)
<< ":"
<< ntohs(si_other_in->sin_port)
<< std::endl;
}//
}
else if(rc == 0)
{
printf("\nEmpty");
}
else if(rc < 0)
{
printf("\nError");
}

}//while

// Close the socket when finished receiving datagrams
wprintf(L"\nFinished receiving. Closing socket.\n");

iResult = ::closesocket(sockListener);

Unfortunately I only get the first 4 bytes of one of the messages while listening .... (which I see in the console) ....
But in the Wireshark sniffer I see that they come !!! Each response has <340 bytes (data)

I will be grateful to you if you can help me! Thanks in advance :)

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900