【问题标题】:Connect Timeout with Alarm()使用 Alarm() 连接超时
【发布时间】:2011-10-28 21:20:36
【问题描述】:

由于我似乎无法找到原始问题的解决方案,因此我尝试了一些解决方法。我只是想为我的 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;
}

这是我在 Internet 上在 stackoverflow 上的一个线程 here 中找到的解决方案。如果我使用此代码,程序将启动计时器,然后进入connect() 调用。 5 秒后,信号处理程序被触发(如控制台上的 printf() 所示),但此后程序仍保留在 connect() 函数中 75 秒。实际上,每个描述都说connect_alarm() 应该中断connect() 函数,但在我的情况下似乎没有。有什么方法可以为我的问题获得所需的结果?

【问题讨论】:

  • 我在一周后解决了我的问题.....thnx...
  • 你是用 sigaction 实现的吗?

标签: c++ sockets connect signals alarm


【解决方案1】:

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

请改用sigaction,不要指定SA_RESTART,您应该可以继续使用。

...

嗯,除了一般的脆弱性和不可避免的竞争条件,就是这样。 connect 将为 any 信号返回 EINTR,而不仅仅是 SIGALARM。更麻烦的是,如果系统恰好负载过重,调用alarm和调用connect之间可能需要5秒以上,这样你就会错过信号并永远阻塞connect .

您之前的尝试是使用带有connectselect 的非阻塞套接字,这是一个更好的主意。我建议调试一下。

【讨论】:

  • sigaction 在 connect() 上对我不起作用。 openSuSe 12 64 位。我已经清除了所有的 SA 标志。
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-01
    • 2022-01-21
    • 1970-01-01
    • 2017-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多