Question

I have a UDP client which has to receive form two different sockets.
I am using select system call to multiplex the recv call.

But I am seeing that the client is blocked inside the second recv call.

How can I resolve this issue?

struct timeval timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;
int activity;

FD_ZERO(&socketfds);
FD_SET(usocket,&socketfds);
max_sd = std::max(max_sd, usocket);
FD_SET(msocket,&socketfds);
max_sd = std::max(max_sd, msocket);
rset = socketfds;

do
{
      rset = socketfds;
      activity = select( max_sd + 1 , &rset , NULL , NULL , &timeout);
}
while(activity<0 && errno == EINTR);

if ((activity < 0) && (errno!=EINTR))
{
     printf("select error");
}
if(FD_ISSET(usocket, &socketfds))
{
      int len;
      printf("Receiving from unicast socket..\n");
      if((len = recvfrom(usocket, dataBuffer, dataLength, 0, (struct sockaddr *)  
   &clientAddr, &clen) < 0) )
     {
           printf("Error reading message \n");
           close(msocket);
           exit(-1);
     }
     else
     {
             printf("Size of message: %d\n", strlen(dataBuffer));
             handleMessage(dataBuffer);
     }
}
if(FD_ISSET(msocket, &socketfds))
{
     printf("Receiving from multicast socket..\n");
     if((recvfrom(msocket, dataBuffer, dataLength, 0, (struct sockaddr *)  
   &multicastClientAddr, &mlen) < 0) )
    {
       printf("Error reading message \n");
       close(msocket);
       exit(-1);
    }
    else
    {
      printf("Message from server:%s\n", dataBuffer);
      handleMessage(dataBuffer);
    }
}
Was it helpful?

Solution

You need to check the rset returned (modified) by select to see if the sockets are ready to read -- the bits will ALWAYS be set in socketfds since that is your master set of sockets to wait for. So change the

if(FD_ISSET(Xsocket, &socketfds))

lines to

if(FD_ISSET(Xsocket, &rset))

OTHER TIPS

The problem, I think, is that you are not taking into account the timeout, select return 0 when it times out. In this case, when returns 0, I do not know how the rset struct will be, may be undifined or untouched. If you want to wait infinity put a NULL in place of timeout.

You should change the condition of the do-while loop. Select returns a non-zero value (the number of fds that have an event) only if there is some event. In your case, it will return the number of fds that have read events. So, if one of the fds has a read event, then select() will return 1 and if both have read events, then select will return 2. And if (activity == 0), then hte number of fds with read-event is zero and so if you call recvfrom(), then that is naturally going to block.

while(activity <= 0 && errno == EINTR);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top