TCP keep_alive не работает, если вы отключите Wi-Fi, чтобы вызвать внезапную потерю соединения - PullRequest
0 голосов
/ 04 ноября 2019

Сценарий:
У меня есть клиент и сервер, написанные с использованием boost :: asio 1.63 . Я использую функцию keep_alive в сокетах tcp для обнаружения потери соединения.

Ниже приведена настройка кода keep_alive.

boost::asio::io_service      ioService;
boost::asio::ip::tcp::socket mySocket(ioService);

#ifdef __APPLE__

    unsigned int timeoutMillis = 2000;
    struct timeval tvs;
    tvs.tv_sec  = timeoutMillis / 1000;
    tvs.tv_usec = (timeoutMillis % 1000) * 1000;
    if (setsockopt(mySocket.native_handle(), SOL_SOCKET, SO_RCVTIMEO, &tvs, sizeof(tvs)) == -1) {
        throw std::logic_error("Cannot set SO_RCVTIMEO");
    }
    if (setsockopt(mySocket.native_handle(), SOL_SOCKET, SO_SNDTIMEO, &tvs, sizeof(tvs)) == -1) {
         throw std::logic_error("Cannot set SO_RCVTIMEO");
    }

#elif __linux__

    int32_t timeout = 2;
    int32_t cnt = 1;
    int32_t interval = 2;
    if (setsockopt(mySocket.native_handle(), SOL_TCP, TCP_KEEPIDLE, &timeout, sizeof(timeout)) == -1) {
        throw std::logic_error("Cannot set TCP_KEEPIDLE");
    }
    if (setsockopt(mySocket.native_handle(), SOL_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt)) == --1) {
        throw std::logic_error("Cannot set TCP_KEEPCNT");
    }
    if (setsockopt(mySocket.native_handle(), SOL_TCP, TCP_KEEPINTVL, &interval, sizeof(interval)) == -1) {
        throw std::logic_error("Cannot set TCP_KEEPINTVL");
    }
#elif WIN32

У меня есть boost::asio::async_read с обеих сторон, всегда ожидающих данных. Он возвращает ошибку, когда другой узел выходит. Следовательно, потеря соединения обнаружена. Эта логика хорошо работает как на Linux на стороне сервера, так и на Android на стороне клиента.

Вопрос:
ЕслиЯ правильно покидаю одноранговый узел, нажимая кнопку «Закрыть», и все работает хорошо. Если я отключу Wi-Fi на моем Android-устройстве, то через 2 секунды я получу сообщение об ошибке. Но , этого не происходит.

Я также тестировал этот код на macOS. Это точно такая же проблема! Как это происходит в случае « выхода из процесса », разве я не должен ожидать ошибочного возврата от boost::asio::async_read также, когда / если Wi-Fi выключен? Объяснение в keep_alive гласит, что оно работает, даже когда ядро ​​на стороне сервера падает. Мне не хватает еще нескольких свойств, которые нужно установить в моем сокете tcp?

...