Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Receiving response(s) from N number of clients in reply to a broadcast request over UDP

I am implementing a kind of IP finder for a particular type of network multimedia device. I want to find out all the alive devices of that type in the LAN, 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 LAN via UDP.
The destination port number is fixed.
In reply, all the servers in the LAN that understand the format of this request will respond to this request providing information about themselves.

I am broadcasting the UDP request message using sendto().

Now my problem is that I don't know how many devices (i.e.servers) will respond to the request.

How many times will I have to call recvfrom()?
When will I come to know that I have handled the response from all the devices?
Or in general, is recvfrom() the right choice for receiving response from multiple servers?
Is there any better (or CORRECT if I am wrong here) way of accomplishing the same?

I am programming in C/C++, planning to code for both Windows and Linux.
Many thanks in advance.

Edit: So with the help of all the network programming wizards out here, I have found the solution to my problem :)
select() is just the thing for me...
Thanks a lot to all of you who took out time to help me

like image 697
puffadder Avatar asked Mar 02 '10 16:03

puffadder


2 Answers

How many times will I have to call recvfrom()? When will I come to know that I have handled the response from all the devices/servers?

If you don't know the number of devices/servers, you cannot know how many times you will need to call recvfrom() or when you've handled all the responses.

You might consider using a select() loop (until timeout) and call recvfrom() when data is available to read. This might be in the main thread or a separate thread.

If the data arrives faster than it can be processed, you will lose datagrams. This will depend largely on the speed that the data is parsed and stored after it is received. If processing the data is an intensive operation, it may be necessary to do the processing in a separate thread or store the data until the receive loop times out and then proceed with processing it.

Since UDP is unreliable, looping to rebroadcast a few times should help account for some of the loss and the processing should account for duplicates.

The following pseudocode is how I might approach the problem:


/* get socket to receive responses */
sd = socket( ... );

do
{
    /* set receive timeout */
    timeout.tv_sec = 5;     

    /* broadcast request */
    sendto( ... );

    /* wait for responses (or timeout) */
    while(select(sd+1, &readfds, NULL, NULL, &timeout) > 0)
    {
        /* receive the response */
        recvfrom( ... );

        /* process the response (or queue for another thread / later processing) */
        ...

        /* reset receive timeout */
        timeout.tv_sec = 5; 
    }

    /* process any response queued for later (and not another thread) */

} while (necessary);

Or in general, is recvfrom() the right choice for receiving response from multiple servers?

recvfrom() is commonly used with connectionless-mode sockets because it permits the application to retrieve the source address of received data.

like image 174
9 revs Avatar answered Nov 18 '22 11:11

9 revs


Use a select(2)/poll(2) with a timeout in a loop, decrementing the timeout every time you get a response from a device. You'd have to come up with appropriate timeout yourself.

Alternatively, if you are able to recognize/parse the discovery response message, just add the device to the list upon receiving such message.

You will probably have to deal with timeouts anyway for when devices register but fail at a later point.

like image 2
Nikolai Fetissov Avatar answered Nov 18 '22 10:11

Nikolai Fetissov