Boost ASIO psát baví, když se zařízení odpojí

0

Otázka

Mám server aplikace, která používá boost ASIO komunikovat s několika klienty. Serverová aplikace běží na Linux serveru a klienti běží na počítačích se systémem Windows.

Současný design je multi-threaded i když tam je jen jeden boost ASIO thead (který běží boost::asio::io_context). Boost ASIO vlákno je odpovědný pouze pro čtení, psaní, a některé občasné odeslání. Čtení se provádí pomocí boost::asio::async_read ale kopie výsledné zprávy tak, že se další vlákno může dělat práci zpracování. Psaní se provádí pomocí boost::asio::write ale zpráva již byla zkopírována a předán boost ASIO závit

Ve většině případů, kdy se klient odpojí boost ASIO vyhodí chybu, vypnul jsem souborům zásuvky a ostatní zásuvky pokračovat v práci. Však pokud klient je Windows desktop má výpadku napájení, zatímco boost::asio::write je psaní pro ně pak zvýšit nerozpozná problém, a visí v boost::asio::write. Visí na téměř 20 minut, někdy a server nemůže komunikovat s ostatními klienty během této doby

Z toho, co jsem četl, on-line autoři boost ASIO nemám v úmyslu zavést parametr timeout. Zkoušel jsem nastavení SO_SNDTIMEO na 5 sekund, ale to nemělo žádný vliv na zápis pověsit. Jak nyní, můj nejlepší odhad, jak vyřešit problém je to, aby každý socket jiném vlákně tak, že jeden klient nemůže sundat další klienty. Existují nějaké lepší možnosti než tohle? Jestli mám dát každé zásuvky jeho vlastní vlákno, znamená to, že budu potřebovat boost::asio::io_context za nit, aby se zabránilo psát pověsit?

Edit: Po shlédnutí komentářů jsem se snažil předělání funkce, která se volá boost::asio::write s boost::asio::async_write. Níže jsem nějaký kód, který byl zjednodušen TAK, ale stále ukazuje, jaké celkové změny bylo:

Původně s 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();
    });
}

Přepracován s 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();
            }
        );
    });
}

Zámek byl představen v druhé kód zaručit pouze jeden hovor boost::asio::async_write byl aktivní v době, (jsem si vědom, že existují výkonnější způsoby, jak to udělat, ale je to jednodušší pro testování). Oba tyto kódy mají stejný problém visí boost ASIO, kdy klient má výpadku napájení. Nicméně oni nemají viset v různých způsobů, asynchronní kód neumožňuje pro boost ASIO provádět jiné akce, jen tak dále píše, dokud visí jeden produkuje chybě

Při samostatném experimentu zkoušel jsem nastavení SO_KEEPALIVE ale to také neřeší problém pověsit

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

Nejlepší odpověď

1

Souhlasím s commenters, že to je to, jak TCP obecně funguje.

Všimněte si, že můžete zavést časové limity pomocí ASIO časovač, který vám umožní zrušit aynchronous operace na vašem zásuvky.

Existuje mnoho, mnoho příkladů, pokud budete hledat

  • boost::asio::steady_timer, oost::asio::high_resolution_timer a obdobné členové std::chrono rodinné hodin
  • boost::deadline_timer
2021-11-22 22:29:35

V jiných jazycích

Tato stránka je v jiných jazycích

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