Aumentar ASIO escrever travar quando o dispositivo desliga

0

Pergunta

Eu tenho um servidor de aplicativo que usa o boost ASIO para se comunicar com vários clientes. A aplicação de servidor é executado em um servidor Linux e clientes executar em ambientes de trabalho do Windows.

O design atual é multi-threaded embora haja apenas um impulso ASIO thead (que é executado boost::asio::io_context). O impulso ASIO thread só é responsável para a leitura, a escrita, e alguns raros envio. A leitura é feita usando boost::asio::async_read mas copia a mensagem resultante, de modo que outro thread pode fazer o trabalho de processamento. A escrita é feita usando boost::asio::write mas a mensagem já foi copiado e entregue para o impulso ASIO thread

Na maioria das circunstâncias, quando um cliente se desconecta impulso ASIO lança um erro, eu encerrar o associado tomada, e a outra sockets continuar a trabalhar. No entanto, se um cliente da área de trabalho do Windows tem uma falha de energia durante boost::asio::write é escrever a eles, em seguida, impulsionar não detectar um problema e trava em boost::asio::write. Ele trava por quase 20 minutos e, por vezes, o servidor não pode se comunicar com outros clientes durante este tempo

Pelo que tenho lido online os autores de impulsionar o ASIO não tenho nenhuma intenção de introduzir um parâmetro de tempo limite. Eu tentei definição SO_SNDTIMEO para 5 segundos, mas que não tem qualquer efeito sobre a escrever travar. A partir de agora meu melhor palpite para resolver o problema é o de dar a cada soquete de um thread diferente, de modo que um cliente não pode derrubar os outros clientes. Existem opções melhores do que este? Se eu não dar a cada um o soquete seu próprio thread isso significa que vai precisar de um boost::asio::io_context por thread para evitar a gravação de travar?

Edit: Depois de ver os comentários eu tentei refazer a função que chama boost::asio::write com boost::asio::async_write. Abaixo eu fiz um código que foi simplificado para ISSO, mas ainda mostra que a variação global foi:

Originalmente com boost::asio::write:

inline void MessagingServer::writeMessage(
    GuiSession* const  a_guiSession,
    const PB::Message& a_msg
) {
    boost::asio::dispatch(m_guiIoIoContext, [this, a_guiSession, a_msg]() {
        // I removed code that writes a_msg's bytes into m_guiIoWriteBuf
        // and sets totalSize to simplify for SO

        boost::system::error_code error;
        boost::asio::write(a_guiSession->m_guiIoGsSocket, boost::asio::buffer(m_guiIoWriteBuf, totalSize), error);
        if (UNLIKELY(error))
            ERRLOG << a_guiSession->m_gsSessionId << " write failed: " << error.message();
    });
}

Refeito com boost::asio::async_write:

inline void MessagingServer::writeMessage(
    GuiSession* const  a_guiSession,
    const PB::Message& a_msg
) {
    a_guiSession->m_tempMutex.lock();

    boost::asio::dispatch(m_guiIoIoContext, [this, a_guiSession, a_msg]() {
        // I removed code that writes a_msg's bytes into m_guiIoWriteBuf
        // and sets totalSize to simplify for SO

        boost::asio::async_write(
            a_guiSession->m_guiIoGsSocket,
            boost::asio::buffer(m_guiIoWriteBuf, totalSize),
            [this, a_guiSession](const boost::system::error_code& a_error, std::size_t) {
                if (UNLIKELY(a_error))
                    ERRLOG << a_guiSession->m_gsSessionId << " write failed: " << a_error.message();

                a_guiSession->m_tempMutex.unlock();
            }
        );
    });
}

O bloqueio foi introduzido o segundo código para garantir que apenas uma chamada para boost::asio::async_write foi ativo por vez (estou ciente de que existem mais alto desempenho maneiras de fazer isso, mas isso é mais simples para teste). Ambos estes códigos têm o mesmo problema de suspensão impulso ASIO quando o cliente tem uma falha de energia. No entanto, eles não reagir de maneiras diferentes, o código assíncrono permite aumentar ASIO para realizar outras ações, apenas não mais escreve, até a de suspensão produz um erro

Durante separado experimento que eu fiz tente definir SO_KEEPALIVE mas que também não conseguiu resolver o problema de travar

asio boost c++ multithreading
2021-11-22 19:46:12
1

Melhor resposta

1

Eu concordo com os comentaristas que este é como o TCP, de um modo geral.

Observe que você pode introduzir limites de tempo, usando ASIO timer que permite cancelar aynchronous operações em seus soquetes.

Há muitos exemplos, se você procura por

  • boost::asio::steady_timer, oost::asio::high_resolution_timer e análogo membros do std::chrono família de relógios
  • boost::deadline_timer
2021-11-22 22:29:35

Em outros idiomas

Esta página está em outros idiomas

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................