Boost ASIO écrire accrocher lorsque l'appareil se déconnecte

0

La question

J'ai un serveur d'application qui utilise boost ASIO pour communiquer avec plusieurs clients. Le serveur d'application s'exécute sur un serveur Linux et les clients de fonctionner sur Windows ordinateurs de bureau.

La conception actuelle est multi-thread bien qu'il n'existe qu'un coup de pouce ASIO thead (qui s'exécute boost::asio::io_context). Le coup de pouce ASIO thread n'est responsable que pour la lecture, l'écriture, et quelques rares expédition. La lecture se fait à l'aide de boost::asio::async_read mais copie le message résultant de sorte qu'un autre thread peut faire le travail de traitement. L'écriture se fait à l'aide de boost::asio::write mais le message a déjà été copié et transmis à l'boost ASIO fil

Dans la plupart des cas, lorsqu'un client se déconnecte boost ASIO renvoie une erreur, j'ai arrêté les associés de socket, et les autres supports de continuer à travailler. Toutefois, si un client Windows desktop a une panne de courant pendant boost::asio::write est écrit, puis boost ne pas détecter un problème et se bloque dans boost::asio::write. Il se bloque pendant près de 20 minutes et le serveur ne peut pas communiquer avec d'autres clients au cours de ce temps

De ce que j'ai lu en ligne, les auteurs de boost ASIO n'ai pas l'intention d'introduire un paramètre de délai d'attente. J'ai essayé de réglage SO_SNDTIMEO à 5 secondes, mais qui n'ont pas eu une incidence quelconque sur l'écriture de l'accrocher. Comme de maintenant, ma meilleure supposition de résoudre le problème est de donner à chaque prise un autre fil de sorte qu'un client ne peut pas prendre vers le bas les autres clients. Existe-il des options de meilleure qualité que cela? Si je dois donner à chaque prise son propre thread est-ce à dire que j'ai besoin d'un boost::asio::io_context par thread pour éviter de l'écrire pendre?

Edit: Après avoir vu les commentaires que j'ai essayé de refaire la fonction qui appelle boost::asio::write avec boost::asio::async_write. Ci-dessous j'ai un code qui a été simplifié pour, mais encore montre que le changement global de l'été:

À l'origine, avec 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();
    });
}

Refait à neuf avec 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();
            }
        );
    });
}

La serrure a été introduit dans le deuxième code, afin de garantir qu'un appel à boost::asio::async_write a été actif à la fois (je suis conscient qu'il y a de plus performant façons de procéder, mais c'est plus simple pour les tests). Ces deux codes ont le même problème de la pendaison de boost ASIO lorsque le client a une panne de courant. Cependant, ils ne pendent de différentes façons, le code asynchrone permet de stimuler ASIO pour effectuer d'autres actions, tout simplement pas écrit en outre, jusqu'à la pendaison on produit une erreur

Dans une autre expérience que j'ai faite essayer de régler SO_KEEPALIVE mais qui ne permet pas de résoudre le problème de blocage

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

La meilleure réponse

1

Je suis d'accord avec les commentateurs qui c'est comment TCP, généralement cela fonctionne.

Notez que vous pouvez introduire des délais d'attente à l'aide d'un ASIO minuterie qui vous permettent d'annuler asynchrone opérations sur vos prises de courant.

Il existe de nombreux de nombreux exemples, si vous recherchez

  • boost::asio::steady_timer, oost::asio::high_resolution_timer et autres membres de la std::chrono de la famille des horloges
  • boost::deadline_timer
2021-11-22 22:29:35

Dans d'autres langues

Cette page est dans d'autres langues

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