Zvýšenie ASIO napísať zavesiť, keď zariadenie odpojí

0

Otázka

Mám server aplikáciu, ktorá používa boost ASIO komunikovať s niekoľkými klientmi. Server aplikácia beží na Linux server a klienti spustiť na Windows počítačoch.

Súčasný dizajn je multi-threaded hoci je tam len jeden boost ASIO thead (ktorý beží boost::asio::io_context). Zvýraznenie ASIO vlákno je zodpovedný len za čítanie, písanie, a niektoré zriedkavé odoslanie. Čítanie je možné pomocou boost::asio::async_read ale kópií výsledné správy tak, že iného vlákna môže robiť prácu spracovanie. Písanie je vykonané pomocou boost::asio::write ale správy už boli skopírované a podal off na podporu ASIO niť

Vo väčšine prípadov, keď klient odpojí boost ASIO hádže chybu, som vypol spojené zásuvka, a iné zásuvky pokračovať v práci. Avšak ak sa klienta na pracovnej ploche systému Windows má moc zlyhanie pri boost::asio::write je písanie, ktoré im potom boost nerozpoznal problém, a visí v boost::asio::write. To visí na takmer 20 minút, niekedy a serverom nemôže komunikovať s ostatnými klientmi počas tejto doby

Z toho, čo som čítal, on-line autori boost ASIO nemajú v úmysle zaviesť časový limit parameter. Snažil som sa nastavenie SO_SNDTIMEO na 5 sekúnd, ale že nemal mať žiadny vplyv na písanie zavesiť. Ako teraz môj najlepší odhad vyriešiť problém je dať každej zásuvky inom vlákne tak, že jeden klient nemôže vziať nadol ostatných klientov. Existujú aj lepšie možnosti, ako toto? Ak by som si dať každý zásuvky svoje vlastné vlákno znamená to, že budem potrebovať boost::asio::io_context za nite, aby sa zabránilo napísať zavesiť?

Edit: Po zhliadnutí komentáre snažil som sa redoing funkciu, ktorá hovory boost::asio::write s boost::asio::async_write. Nižšie som nejaký kód, ktorý bol zjednodušený TAK, ale stále ukazuje, čo je celková zmena bola:

Pôvodne 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();
    });
}

Prepracovaný 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ámok bol predstavený v druhej kód zaručiť iba jeden hovor boost::asio::async_write bol aktívny v čase (som si vedomý, že tam sú ďalšie výkonné spôsoby, ako to urobiť, ale je to jednoduchšie pre testovanie). Obe tieto kódy majú rovnaký problém zavesenie boost ASIO, keď klient má výpadku napájania. Avšak oni to visieť v rôznych spôsobov, asynchrónne kód robí umožňujú zvýšiť ASIO vykonávať iné činnosti, len nie ďalej píše, kým visí jeden produkuje chybu

Počas samostatnej experiment som si vyskúšať nastavenie SO_KEEPALIVE ale to tiež nepodarilo vyriešiť problém zavesiť

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

Najlepšiu odpoveď

1

Som súhlasiť s pripomienky, že je to, ako TCP vo všeobecnosti funguje.

Všimnite si, že môžete zaviesť časové limity, pomocou ASIO časovačom, ktorý vám umožní zrušiť aynchronous operácie na vašej zásuvky.

Existuje mnoho, mnoho príkladov ak ste vyhľadávanie

  • zvýraznenie::asio::steady_timer, oost::asio::high_resolution_timer a podobných členov std::chrono rodiny hodiny
  • zvýraznenie::deadline_timer
2021-11-22 22:29:35

V iných jazykoch

Táto stránka je v iných jazykoch

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