How can I retry sending (let's say using a while loop or something similar) in the following code that I have, whenever I have a timeout? I abridged some parts of my code.
I am not familiar with C error codes and error handling so I don't know where to catch/handle the error and what error code to look for.
sock = socket(create socket....)
if (sock < 0 ) {
exit(EXIT_FAILURE);
}
servaddr initializations.....
sendto(sock, etc etc........);
struct timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,&timeout,sizeof(timeout)) < 0) {
perror("Error");
}
addrlen = sizeof(servaddr);
if(recvfrom (sock, etc, etc......) < 0)
{
printf("revfrom failed.\n");
}
From man 7 socket
:
SO_RCVTIMEO
andSO_SNDTIMEO
:Specify the receiving or sending timeouts until reporting an error. The argument is a
struct timeval
. If an input or output function blocks for this period of time, and data has been sent or received, the return value of that function will be the amount of data transferred; if no data has been transferred and the timeout has been reached, then-1
is returned witherrno
set toEAGAIN
orEWOULDBLOCK
, orEINPROGRESS
(forconnect(2)
) just as if the socket was specified to be nonblocking. If the timeout is set to zero (the default), then the operation will never timeout. Timeouts only have effect for system calls that perform socket I/O (e.g.,read(2)
,recvmsg(2)
,send(2)
,sendmsg(2)
); timeouts have no effect forselect(2)
,poll(2)
,epoll_wait(2)
, and so on.
So, in your case, the code to keep trying if the timeout is reached would look something like this:
struct timeval timeout = {.tv_sec = 5, .tv_usec = 0};
if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) < 0) {
perror("setsockopt failed");
// Handle error
}
// ...
while (sendto(sock, /*...*/) == -1) {
if (errno != EAGAIN && errno != EWOULDBLOCK) {
// Some unexpected error happened.
perror("sendto failed");
}
// Otherwise it was a timeout, just continue trying.
}
Note that SO_SNDTIMEO
is for sending, and SO_RCVTIMEO
is for receiving. If you want to set both then do two setsockopt
calls.
In any case, it seems to me like you are wasting your time with this. If you want to keep trying until you get data, then just don't bother doing any setsockopt
, as the default behavior is to wait indefinitely until data is received:
If the timeout is set to zero (the default), then the operation will never timeout.