每当我有超时时,我如何在下面的代码中重试发送(比如使用while循环或类似的东西(?我删节了代码的某些部分。
我不熟悉C错误代码和错误处理,所以我不知道在哪里捕捉/处理错误以及查找什么错误代码。
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");
}
来自man 7 socket
:
SO_RCVTIMEO
和SO_SNDTIMEO
:指定接收或发送超时,直到报告错误自变量是
struct timeval
。如果输入或输出函数在这段时间内阻塞,并且数据已经发送或接收,则该函数的返回值将是传输的数据量如果未传输任何数据并且已达到超时,则返回-1
,errno
设置为EAGAIN
或EWOULDBLOCK
或EINPROGRESS
(对于connect(2)
(,就像套接字被指定为非阻塞一样。如果超时设置为零(默认值(,则操作将永远不会超时。超时仅对执行套接字I/O的系统调用有效(例如,read(2)
、recvmsg(2)
、send(2)
、sendmsg(2)
(;超时对select(2)
、poll(2)
、epoll_wait(2)
等没有影响
因此,在您的情况下,如果达到超时,则继续尝试的代码看起来像这样:
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.
}
注意SO_SNDTIMEO
用于发送,SO_RCVTIMEO
用于接收。如果要同时设置两者,则执行两个setsockopt
调用。
无论如何,在我看来,你在浪费时间。如果你想一直尝试,直到你得到数据,那么就不要麻烦做任何setsockopt
,因为默认行为是无限期等待,直到收到数据:
如果超时设置为零(默认值(,则操作永远不会超时。