Question

I am using an infinite loop in sockets in which if it receives some data it should receive it or if it wants to send data it sends. Something like given below. I am using select. I have only one socket sd.

fd_set readsd;
int maxsd = readsd +1;
// all those actions of setting maxsd to the maximum fd +1 and FDSETing the FDs.
while(1)
{
     FD_ZERO(&read_sd);
     FD_SET(sd, &read_sd);
     if(FD_ISSET(sd, &readsd))
     {
       //recv call
     }
     else
     {
       //send call
     }
}

As far as I know, select selects one of the socket descriptors on which data arrives first. But here I have only one socket, and I want to recv if there is some data or I want to send otherwise.

In that case, is the code given above fine? Or there is some other option for me which I don't know about?

Was it helpful?

Solution

In that case, is the code given above fine ?

I don't see any call to select. Also, if “maxsd” is designed to be the first argument of select, its value is wrong : it must be the bigest file descriptor +1. Anyway, you could simply call recv with the flag MSG_DONTWAIT, in which case it will return an error if there is no data to read.

OTHER TIPS

It kind of depends... First of all, you actually do have a select call in your real code?

Now about the blocking... If select returns with your socket set in the read-set, then you are guaranteed that you can call recv without blocking. But there are no guarantees about the amount of data available. If you use UDP then there will be at least one (hopefully complete) packet, but if you use TCP you may get only one byte. For some protocols with message boundaries, you might not get full messages, and you have to call recv in a loop to get all of the message, and unfortunately this will sooner or later cause the recv call to block.

So in short, using select helps, but it does not help in all cases. The only way to actually guarantee that a recv call won't block is to make the socket non-blocking.

Im not very sure about what you are trying to do, so I can think about two options:

Set a socket to be non-blocking

Since seems like you have only one socket, you can set the socket to non-blocking mode using fcntl and call the recv()

fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK);
// if fcntl returns no error, sock is now non-blocking

Set the select timer

Using select you can set a timer to force the return after some time happened even if no data was received.

First, I cannot find any select in your code.

However, you may call fcntl(fd, F_SETFL, flags | O_NONBLOCK) first to make your socket non-blocking. Then check if errno == EWOULDBLOCK when you cannot read anything from recv. You need not to use select in this case.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top