问题
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);
}
}
回答1:
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))
回答2:
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.
回答3:
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);
来源:https://stackoverflow.com/questions/18621352/blocking-recvfrom-with-select-system-call