Impulso ASIO escribir colgar cuando el dispositivo se desconecta

0

Pregunta

Tengo una aplicación de servidor que utiliza impulso ASIO para comunicarse con varios clientes. La aplicación de servidor se ejecuta en un servidor Linux y los clientes que se ejecutan en los escritorios de Windows.

El diseño actual es multi-hilo aunque sólo hay un impulso ASIO thead (que se ejecuta boost::asio::io_context). El impulso ASIO hilo sólo es responsable de la lectura, la escritura, y algunos poco frecuentes de envío. La lectura se realiza mediante boost::asio::async_read pero copia el mensaje resultante, de modo que otro subproceso puede hacer el trabajo de procesamiento. La escritura se realiza mediante boost::asio::write pero el mensaje ya ha sido copiado y pasa a las manos del impulso ASIO hilo

Bajo la mayoría de circunstancias cuando un cliente se desconecta del impulso ASIO lanza un error, puedo cerrar el socket asociado, y los otros zócalos de seguir trabajando. Sin embargo, si un cliente de escritorio de Windows tiene un fallo de alimentación mientras boost::asio::write está escrito para ellos, a continuación, impulsar no detecta un problema y se cuelga en boost::asio::write. Se cuelga durante casi 20 minutos y a veces el servidor no puede comunicarse con otros clientes durante este tiempo

Por lo que he leído en línea que los autores de impulso ASIO no tienen la intención de introducir un parámetro de tiempo de espera. Traté de configuración SO_SNDTIMEO a 5 segundos, pero que no tienen ningún efecto en la escritura de colgar. A partir de ahora mi mejor estimación para resolver el problema es dar a cada socket en un subproceso diferente para que un cliente no puede acabar con los otros clientes. Hay mejores opciones que este? Si me dan cada socket su propio hilo significa eso que voy a necesitar una boost::asio::io_context por el hilo para evitar que la escritura se bloquea?

Edit: Después de ver los comentarios que he tratado de rehacer la función que llama a boost::asio::write con boost::asio::async_write. A continuación tienes algún código que se ha simplificado para tanto, pero todavía muestra lo que el cambio general fue:

Originalmente con 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();
    });
}

Remodelada con 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();
            }
        );
    });
}

El bloqueo fue introducido en el segundo código para garantizar a sólo una llamada a boost::asio::async_write se activa en un momento (soy consciente de que hay más eficientes maneras de hacer esto, pero este es más sencillo para las pruebas). Ambos de estos códigos tienen el mismo número de colgantes impulso ASIO cuando el cliente tiene una falla de energía. Sin embargo, se cuelgan en diferentes formas, el código asíncrono permite aumentar ASIO para realizar otras acciones, simplemente no escribe hasta que la cortina se produce un error

Durante un experimento separado, me hizo intentar establecer SO_KEEPALIVE pero que también no se soluciona el problema de bloqueo

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

Mejor respuesta

1

Estoy de acuerdo con los comentaristas que esta es la forma en TCP generalmente funciona.

Tenga en cuenta que puede introducir tiempos de espera con ASIO temporizador que le permite cancelar aynchronous operaciones en sus zócalos.

Hay muchos ejemplos, si usted busca

  • boost::asio::steady_timer, oost::asio::high_resolution_timer y análogos a los miembros de la std::chrono de la familia de relojes
  • boost::deadline_timer
2021-11-22 22:29:35

En otros idiomas

Esta página está en otros idiomas

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