Lets consider following piece of code
pollfd file_descriptors[1];
file_descriptors[0].fd = sock_fd;
file_descriptors[0].events = POLLIN;
int return_value = poll(file_descriptors, 1, 0);
if (return_value == -1) { cerr << strerror(errno); }
else if (return_value == 0) { cerr << "No data available to be read"; }
else {
if (file_descriptors[0].revents & POLLIN) {
recv(sock_fd, buff, 1024, 0);
}
}
Now I have two questions regarding the above code.
-1
nor 0
and sets the POLLIN
flag in the bitmap revents
for the first entry in the file_descriptors
array, then will the call to recv()
block? If no, then will the data be read in instantaneously?poll()
goes the same way as mentioned above. How much data is going to be read in? Is it just going to be the same as a regular call to recv()
? i.e. an arbitrary (to the programmer) amount less than or equal to 1024
in the above case. Then if I want to poll()
before reading again, do I just repeat from the first invocation of poll()
until all data has been read in completely (i.e. in a client server scenario this would correspond to the request being completed)?Thank you!
If the call to poll() returns neither -1 nor 0 and sets the POLLIN flag in the bitmap revents for the first entry in the file_descriptors array, then will the call to recv() block? If no, then will the data be read in instantaneously?
The call to poll
has no effect on the call to recv
. Whether or not recv
blocks depends on what data is available at the time you call recv
and whether the socket is in blocking or non-blocking mode.
Assuming the call to poll() goes the same way as mentioned above. How much data is going to be read in? Is it just going to be the same as a regular call to recv()? i.e. an arbitrary (to the programmer) amount less than or equal to 1024 in the above case. Then if I want to poll() before reading again, do I just repeat from the first invocation of poll() until all data has been read in completely (i.e. in a client server scenario this would correspond to the request being completed)?
Assuming you don't want to block, you should set the socket non-blocking. You have two basic choices. You can call the receive function once and then poll
again. Or you can keep calling receive until you get a "would block" indication. If the socket is a TCP connection, you can keep calling the receive function until you either get a "would block" indication or receive fewer bytes than you asked for.
There are three common, non-blocking I/O strategies that you can base around poll
or select
. All require that the socket be set non-blocking.
1) You can always call poll
or select
before you perform an I/O operation. You then attempt a single read or write operation only if you get a read or write hit from poll
or select
.
2) You can attempt the read
or write
operation first. If it succeeds immediately, great. If not, wait for a poll
or select
hit before retrying the operation.
3) You can call poll
or select
before you perform an I/O operation. You then attempt multiple read
s or write
s until you either finish everything you need to do or get a "would block" indication. When you get a "would block" indication, you wait until select
or poll
tells you before you attempt another operation in that direction on that socket.
Method 3 is probably the most common for reads. Method 2 is probably the most common for writes.
It is very important to keep in mind that poll
is a status reporting function that tells you current information. It does not come with any future guarantees. The assumption that a read indication from poll
means that a future read operation will not block is a mistake and it has caused serious bugs with significant security implications in the past. The only way to guarantee that a socket operation will not block is to set the socket non-blocking.
If the poll()
returns a strictly positive value, it means that at least one of your descriptors has some data to return.
The recv()
SHOULD therefore not be blocking: as there is data it SHOULD return something. In any case, it is not guaranteed that all the 1024 bytes will be returned by the call.
You must therefore check the number of bytes returned by recv()
. Eventually, you have to loop on your polling/receiving until you got all the expected data.
You can control the blocking/non-blocking behaviour either by call with the flag parameter MSG_DONTWAIT
, or via fcntl()
on a more durable fashion.
Edit: Note that if something goes wrong on the socket (for example a loss of connection) the available data promised by the poll MIGHT be lost and block the recv()
against all expectations. It is hence safer to explicitely use the non-blocking flag (and consider that recv()
might return an error code instead of a number of bytes read).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With