使用闹钟连接超时()

时间:2011-08-17 12:18:01

标签: c++ sockets connect signals alarm

由于我似乎无法找到原始问题的解决方案,因此我尝试了一些解决方法。我只是尝试将超时设置为我的TCP套接字的connect()调用。

  1. 我希望connect()被阻止,但直到通常的75秒超时,我想定义自己的。{/ li>
  2. 我已经尝试了select(),但是我无法获得连接(这是我here所述的初始问题。)
  3. 所以现在我找到了另一种方法来处理它:只是做一个阻塞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()函数,但在我的情况下它似乎不是。有没有办法让我的问题得到理想的结果?

2 个答案:

答案 0 :(得分:2)

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

请改用sigaction,不要指定SA_RESTART,你应该好好去。

...

嗯,除了一般的脆弱性和不可避免的竞争条件之外,那就是。 connect将返回EINTR 任何信号,而不只是SIGALARM。更麻烦的是,如果系统遇到重负荷,在拨打alarm和拨打connect之间可能需要5秒以上的时间,在这种情况下你会错过信号并阻塞永远connect

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

答案 1 :(得分:1)

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