【发布时间】:2018-10-02 03:58:52
【问题描述】:
我有一个signal,我在其中设置了一个回调处理程序,然后在我的函数中调用alarm(1),这样我的程序将在1 秒后超时。超时后,我希望它重试相同的阻塞调用recvfrom(),直到设置为 5 的MAX_ATTEMPTS。
问题:
在退出程序之前只重试 2 次。知道可能出了什么问题吗?
/* declate signal for setting alarm */
signal(SIGALRM, timeout_hdler);
int attempts = 0;
while(1) {
if(attempts > MAX_ATTEMPTS) {
printf("Connection is not working, EXITING program");
s.curr_state = CLOSED;
/* we assume connection is failing so we shut down */
exit(-1);
}
if (s.curr_state == CLOSED) {
printf("Sending SYN_packet with seqnum: %d...\n", SYN_packet->seqnum);
if (sendto(sockfd, SYN_packet, sizeof(SYN_packet), 0, server, socklen) == -1) {
perror("Sendto error");
exit(-1);
}
s.curr_state = SYN_SENT;
printf("Current state SYN_SENT: %d\n", s.curr_state);
}
if (s.curr_state == SYN_SENT) {
alarm(1);
attempts++;
printf("\nAttempt number: %d\n", attempts);
printf("Waiting for SYNACK_packet...\n");
if (recvfrom(
sockfd, SYNACK_packet, sizeof(*SYNACK_packet), 0, (struct sockaddr *) &server, &socklen) == -1)
{
if (errno != EINTR) {
perror("Recvfrom SYNACK_packet error\n");
s.curr_state = CLOSED;
exit(-1);
}
}
if ((SYNACK_packet->type == SYNACK) && (validate_packet(SYNACK_packet) == 1)) {
printf("SYNACK_packet received\n");
s.address = *(struct sockaddr *) &server;
s.sock_len = socklen;
s.curr_state = ESTABLISHED;
s.seq_num = SYNACK_packet->seqnum;
printf("Current state ESTABLISHED: %d\n", s.curr_state);
return sockfd;
}
}
}
处理程序(除了打印什么都不做):
void timeout_hdler(int signum) {
printf("TIMEOUT has occured with signum: %d", signum);
}
这是我控制台中的输出(来自printf 语句):
In Connect() with socket: 4, server: 2, socklen: 16
Sending SYN_packet with seqnum: 67...
Current state SYN_SENT: 1
Attempt number: 1
Waiting for SYNACK_packet...
TIMEOUT has occured with signum: 14
Attempt number: 2
Waiting for SYNACK_packet...
Alarm clock
为什么只尝试了 2 次就退出程序?理想情况下,我希望它在关闭连接之前重试 5 次(这是使用 UDP 的 Go Back N 实现)
更新
我通过在我的处理程序中重新安装 signal: signal(SIGALRM, timeout_hdler); 解决了这个问题。但这是为什么呢?我做错了吗?
void timeout_hdler(int signum) {
printf("TIMEOUT has occured with signum: %d", signum);
signal(SIGALRM, timeout_hdler);
}
【问题讨论】:
-
请参阅How to avoid using
printf()in signal handlers,了解有关您的信号处理程序为何不可靠的信息。另见What is the difference betweensigaction()andsignal()? -
请参阅How to create a Minimal, Complete, and Verifiable example 并发布一个完整的示例。
-
@LuisColorado 这是什么意思,这是一个完整、最小且可验证的示例
-
@JonathanLeffler,信号在 linux 内核中不可靠,它们在 BSD 中,但在 linux 中不可靠,即使使用
sigaction(2)。您只会收到第一个,如果您收到了多个信号且该信号被阻止,您将不会收到多个。 -
@LuisColorado 不,它在我的情况下效果很好。感谢乔纳森