Тайм-аут соединения с тревогой () - PullRequest
3 голосов
/ 17 августа 2011

Поскольку мне кажется, что я не могу найти решение своей первоначальной проблемы, я попытался сделать небольшой обходной путь. Я просто пытаюсь установить время ожидания для вызова 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(), но, похоже, в моем случае это не так. Есть ли способ получить желаемый результат для моей проблемы?

Ответы [ 2 ]

2 голосов
/ 18 августа 2011

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

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

...

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

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

1 голос
/ 18 августа 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...