将超时与 Alarm() 连接

问题描述 投票:0回答:2

由于我似乎无法找到原始问题的解决方案,因此我尝试做一些解决方法。我只是想为 TCP 套接字的

connect()
调用设置超时。

  1. 我希望
    connect()
    被阻塞,但直到通常的 75 秒超时为止,我想定义我自己的。
  2. 我已经尝试过
    select()
    ,它可以解决超时问题,但我无法建立连接(这是我最初的问题,如here所述)。

所以现在我找到了另一种方法来处理它:只需执行一个阻塞的

connect()
调用,但用这样的警报中断它:

    signal(SIGALRM, connect_alarm);
    int secs = 5;
    alarm(secs);
    if (connect(m_Socket, (struct sockaddr *)&addr, sizeof(addr)) < 0 )
    {
        if ( errno == EINTR )
        {
            debug_printf("Timeout");
            m_connectionStatus = STATUS_CLOSED;
            return ERR_TIMEOUT;
        }
        else
        {
            debug_printf("Other Err");
            m_connectionStatus = STATUS_CLOSED;
            return ERR_NET_SOCKET;
        }
    }

static void connect_alarm(int signo)
{
     debug_printf("SignalHandler");
     return;
}

这是我在互联网上的 stackoverflow 上的一个线程 here 中找到的解决方案。如果我使用此代码,程序将启动计时器,然后进入

connect()
调用。 5 秒后,信号处理程序被触发(如控制台上的
printf()
所示),但此后程序仍保留在
connect()
函数中 75 秒。实际上,每个描述都说
connect_alarm()
应该中断
connect()
功能,但在我的情况下似乎并非如此。有什么办法可以得到我的问题想要的结果吗?

c++ sockets signals alarm
2个回答
2
投票

signal
是一个严重未指定的接口,应在新代码中避免。在某些版本的 Linux 上,我相信它提供了“BSD 语义”,这意味着(除其他外)默认提供
SA_RESTART

使用

sigaction
代替,不要指定
SA_RESTART
,就可以开始了。

...

好吧,除了普遍的脆弱性和不可避免的竞争条件之外。

connect
将为
任何
信号返回 EINTR,而不仅仅是
SIGALARM
。更麻烦的是,如果系统负载很重,调用
alarm
和调用
connect
之间可能需要超过 5 秒的时间,这样你就会错过信号并永远阻塞在
connect
中.

您之前的尝试,使用带有

connect
select
的非阻塞套接字,是一个更好的主意。我建议调试它。


1
投票

虽然设置

alarm(2)
相对容易(减少信号处理和系统调用中断的痛苦),但超时 TCP 连接尝试的更有效方法是
non-blocking connect
,它也允许您启动多个连接并等待所有连接,一次处理一个成功和失败。

© www.soinside.com 2019 - 2024. All rights reserved.