You can use the select function, described here:select(2) - Linux manual and here: windows API select Function
Note: fd = file Descriptor, I will call it descriptor
The select function works on several descriptors at the same time, it tests with a timeout if a certain operation is available in the given descriptors, such descriptors are contained in structures fd_set
, this structure is manipulated by the macros:
FD_ZERO
: Takes as parameter an fd_set and initializes it
FD_SET
: Takes as parameter a descriptor(your socket) and inserts it into the specified fd_set
FD_ISSET
: Rebece as parameter a descriptor and tests if it is contained in fd_set
The function takes three fd_set’s: the first contains the descriptors that will be used to test read operations, the descriptors of the second are for testing write operations and the third for checking errors. The first function parameter is a number indicating the largest fd that is contained in all fd_set’s passed plus one (this is ignored in windows). The last parameter is a structure timeval
which has two fields:
sec
: time in seconds
usec
: the time in microseconds
The two together specify how long the function should wait until an operation is available. If you pass null
function will lock until at least one operation is available.
When the function returns the fd_set’s passed will contain only the fd’s that are available for the requested operation.
In windows the function is in the header:winsock2.h
(remembering that it replaces the winsock.h
), already in linux you must include sys\select.h
and sys\time.h
, I think these are enough, but the link I reported uses:
/* According to POSIX.1-2001 */
#include <sys/select.h>
/* According to earlier standards */
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
Example of use:
enum OPERATION
{
READ = 0,
WRITE,
EXCEPTION
};
bool testOperation(uint16 sock, OPERATION operation, long milliseconds)
{
int r;
//o primeiro membro da struct é o tempo em segundos e o segundo é o tempo em microsegundos
struct timeval timeout = { milliseconds/1000, 0};
fd_set fds;
FD_ZERO(&fds);
FD_SET(sock, &fds);
switch (operation)
{
case READ:
//observe que é possível passar fd_set's nulos
r = select(sock + 1, &fds, NULL, NULL, &timeout);
break;
case WRITE:
r = select(sock + 1, NULL, &fds, NULL, &timeout);
break;
case EXCEPTION:
r = select(sock + 1, NULL, NULL, &fds, &timeout);
break;
}
if (r == SOCKET_ERROR){/*erro*/}
//operação está disponível
if (FD_ISSET(sock, &fds))
return true;
return false;
}
This is a code I had on github but I didn’t use the timeout, I edited it now and I didn’t test the code because I’m at work and I can’t test it here, but this should work, if not, should at least direct you to the answer.
EDITED
I created two snippets on github to demonstrate use with two client/server programs:
client
server
Both use timeout, tested only in windows.