2
votes

I want to make a multi client - one server quiz application. In this, firstly, the clients will connect to the server and will registered themselves. Then, the server will multicast a question to every client, who have registered themselves to the server. The clients will then respond with the answer, which will be send only to the server. And then server will send the the score of each client to the respective client.
This is what I am trying to do in the above application-
1. As I have too multicast, thats why I am Making my server socket asSOCK_DGRAM (i.e.,UDP). Then I am using CLASS-D ip address, for making a group( to which server will multicast). Then is using setsockopt, I am adding the clients to this group, so that they can recieve the question.
2.As I want to listen the answers from all the clients, so I was thinking of using select. It uses the socket descriptor to select between various clients, as to know which is ready for reading.
But the problem is, when I am using SOCK_DGRAM socket, it doesnot perform listen and accept functionality. So, I will not get a socket descriptor(which is returned by accept). Thats why, I will not be able to use select(as it uses only file descriptors).
So, how am I to proceed, as I want to use UDP functionality - MULTICASTING, as well as TCP functionality - a socket descriptor for each connection.

3
You don't really need multicast, just loop over all connections in the server and send the same message to each client. As for the select problem, you can listen on UDP sockets, and use connect on the clients and accept in the server without problems, just like for TCP.Some programmer dude
Actually, I want that every client in the network should receive the question at the same time, thats why I was thinking of multicasting. If I'll loop it over all connections, then does it guarantees that, the question will reach the clients at the same time? And also does multicasting is a guarantee that all clients will receive the question at the same time(if we ignore RTT delay)vidzi
You still can't guarantee that the message will reach the clients at the same time, and when you factor in that some clients may not get the message (remember that UDP is unreliable) it gets even worse. Looping over even hundreds of clients sending TCP packages is still fast enough for your clients to not notice the difference even if all of them are on a local network.Some programmer dude
When I use a loop, I am actually sending back to back messages to different clients(i.e, sequentially data transfer from my socket). So, but if I'll use multicasting, how is the data actually transfered from my socket, which makes it fast? I mean, is there any kind of parallel sending being done in multicasting or is there any other reason behind it being fast?vidzi
If you use UDP (which I strongly recommend against as you know) and looping, you do send all messages through the same socket, and the kernel will try to send those as soon as it can. If you use multicasting, you only send the message once, and let the kernel do the looping over the sockets in the multicast group. If you are really worried about a few milliseconds delay (and that's on a local network, will be much larger on the open Internet) between clients receiving your messages you should profile. Test all combinations, and select the one you feel is best.Some programmer dude

3 Answers

3
votes

Even when using UDP and unconnected sockets, you can still use functions like select. Simply bind the server socket to an address, and use that socket for select. When the socket is readable a client has sent something with e.g. sendto and you can do e.g. recvfrom.

However, I would really recommend you to use TCP sockets, it will make many things simpler, especially when it comes to the communication protocol (remember that UDP packages can be lost or come out of order, you have to handle that yourself).

0
votes

As you said, select is not usefull here since you only have one socket on the server side. This socket is used to send datagrams with sendto

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
                      const struct sockaddr *dest_addr, socklen_t addrlen);

in dest_addr you specify the destination address for the datagram.

Using recvfrom(2) on a UDP socket is similar :

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                        struct sockaddr *src_addr, socklen_t *addrlen);

src_addr is the sender address, so you are able to identify the client which has sent the response.

recvfrom calls are blocking until data are available for reading (unless you set the socket to unblocking).

You could just loop to receive all the responses.

0
votes

You're on the right track but you don't need listen() or accept(). Just select for readability. When the socket becomes readable, read it. You probably don't need select() for this at all, really, just a blocking read, with a timeout if you like.