Reputation: 81
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?
Upvotes: 0
Views: 14709
Reputation: 2310
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.
Upvotes: 0
Reputation: 1599
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.
Upvotes: 2
Reputation: 333
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.
Upvotes: 3
Reputation: 409176
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.
Upvotes: 2