Boost ASIO scrie atârnă atunci când dispozitivul se deconectează

0

Problema

Am un server de aplicație care utilizează boost ASIO pentru a comunica cu mai mulți clienți. Aplicația server ruleaza pe un server Linux și clienții rula pe desktop-ul Windows.

Designul actual este multi-threaded deși există doar un singur boost ASIO thead (care ruleaza boost::asio::io_context). Boost ASIO subiect este responsabil doar pentru citire, scriere, și unele rare de expediere. Citirea se face cu ajutorul boost::asio::async_read dar copii care rezultă mesaj, astfel încât un alt thread poate face munca de prelucrare. Scrierea se face cu ajutorul boost::asio::write dar mesajul a fost deja copiat si dat afara pentru boost ASIO fir

În cele mai multe cazuri, atunci când un client se deconectează boost ASIO aruncă o eroare, am închis asociat socket, și alte prize ține de lucru. Cu toate acestea, dacă un client desktop pentru Windows are o pană de curent în timp ce boost::asio::write este scris pentru ei, atunci boost nu detecta o problemă și se blochează în boost::asio::write. Se blochează de aproape 20 de minute, uneori și serverul nu poate comunica cu alți clienți în acest timp

Din ce am citit online, autorii boost ASIO au nici o intenție de a introduce o pauză parametru. Am incercat setarea SO_SNDTIMEO la 5 secunde, dar care nu au nici un efect asupra scrie bloca. Ca de acum bănuiala mea de a rezolva problema este de a oferi fiecare mufa un fir diferit, astfel că un client nu poate să ia pe alți clienți. Există opțiuni mai bune decât asta? Dacă eu dau de fiecare priza firul asta înseamnă că va avea nevoie de un boost::asio::io_context pe fir pentru a evita scrie stea?

Edit: Dupa ce am vazut comentarii am încercat refacerea funcția pe care o solicită boost::asio::write cu boost::asio::async_write. Mai jos am un cod care a fost simplificat pentru ATÂT, dar încă arată ce schimbare totală a fost:

Inițial cu 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();
    });
}

Refăcut cu 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();
            }
        );
    });
}

De blocare a fost introdus în cel de-al doilea cod pentru a garanta un singur apel la boost::asio::async_write a fost activ la un moment dat (sunt conștient de faptul că există mai performante moduri de a face acest lucru, dar acest lucru este mai simplu pentru testare). Ambele coduri au aceeași problemă de agățat boost ASIO atunci când clientul are o pană de curent. Cu toate acestea ei fac atârnă în diferite moduri, codul asincron permite pentru boost ASIO pentru a efectua alte acțiuni, nu mai scrie până la agățat unul produce o eroare

În timpul unui experiment separat am încercat stabilirea SO_KEEPALIVE dar care, de asemenea nu a rezolvat problema stea

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

Cel mai bun răspuns

1

Sunt de acord cu comentatori că acest lucru este modul TCP, în general, funcționează.

Rețineți că puteți introduce timeout-uri folosind o ASIO timer care vă permite să anulați aynchronous operațiuni pe prize.

Există multe exemple în cazul în care căutați

  • boost::asio::steady_timer, oost::asio::high_resolution_timer și analog membrii std::chrono familie de ceasuri
  • boost::deadline_timer
2021-11-22 22:29:35

În alte limbi

Această pagină este în alte limbi

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