Соединить тайм-аут с будильником()

Поскольку кажется, что я не могу найти решение своей первоначальной проблемы, я попытался найти небольшой обходной путь. Я просто пытаюсь установить тайм-аут для вызова connect() моего TCP-сокета.

  1. Я хочу, чтобы connect() блокировался, но не раньше обычного тайм-аута в 75 секунд, я хочу определить свой собственный.
  2. Я уже пробовал select(), который работал в течение тайм-аута, но я не мог установить соединение (это была моя первоначальная проблема, как описано здесь ).

Итак, теперь я нашел другой способ справиться с этим: просто сделайте блокирующий вызов 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. Если я использую этот код, программа запускает таймер, а затем переходит к вызову connect(). Через 5 секунд запускается обработчик сигнала (как видно на консоли с printf()), но после этого программа все еще остается в функции connect() в течение 75 секунд. На самом деле в каждом описании говорится, что connect_alarm() должна прерывать функцию connect(), но в моем случае это не так. Есть ли способ получить желаемый результат для моей проблемы?


person Toby    schedule 17.08.2011    source источник
comment
я решил свою проблему через неделю.....спасибо...   -  person Nirav Jain    schedule 06.06.2012
comment
Вы реализовали это с помощью sigaction ?   -  person ernesto    schedule 21.08.2013


Ответы (2)


signal — это сильно недоопределенный интерфейс, и его следует избегать в новом коде. Я полагаю, что в некоторых версиях Linux он обеспечивает «семантику BSD», что означает (среди прочего) предоставление SA_RESTART по умолчанию.

Вместо этого используйте sigaction, не указывайте SA_RESTART, и вы должны идти.

...

Ну, за исключением общей хрупкости и неизбежных условий гонки, то есть. connect вернет EINTR для любого сигнала, а не только SIGALARM. Более хлопотно, если система окажется под большой нагрузкой, между вызовом alarm и вызовом connect может пройти более 5 секунд, и в этом случае вы пропустите сигнал и навсегда заблокируете connect.

Ваша предыдущая попытка с использованием неблокирующих сокетов с connect и select была гораздо лучшей идеей. Я бы предложил отладить это.

person Nemo    schedule 18.08.2011
comment
sigaction не работает для меня при подключении(). опенсусе 12 64бит. Я очистил все флаги SA. - person ernesto; 26.08.2013

Хотя настроить alarm(2) (меньше проблем с обработкой сигналов и прерыванием системных вызовов), более эффективным способом тайм-аута попыток подключения TCP является non-blocking connect, который также позволяет вам инициировать несколько подключений и ожидать их всех, обрабатывая успехи и неудачи по одному за раз.

person Nikolai Fetissov    schedule 18.08.2011