Cihaz bağlantısı kesildiğinde ASIO yazma askıda kalmasını artırın

0

Soru

Birkaç istemciyle iletişim kurmak için boost ASIO kullanan bir sunucu uygulamam var. Sunucu uygulaması bir Linux sunucusunda çalışır ve istemciler Windows masaüstlerinde çalışır.

Mevcut tasarım çok iş parçacıklı olsa da, yalnızca bir boost ASIO thead (çalışır boost::asio::io_context). Boost ASIO iş parçacığı yalnızca okuma, yazma ve bazı seyrek gönderimden sorumludur. Okuma kullanılarak yapılır boost::asio::async_read ancak elde edilen mesajı kopyalar, böylece başka bir iş parçacığı işleme işini yapabilir. Yazma kullanılarak yapılır boost::asio::write ancak mesaj zaten kopyalandı ve boost ASIO iş parçacığına aktarıldı

Çoğu durumda, bir istemci boost ASIO bağlantısını kestiğinde bir hata atar, ilişkili soketi kapatırım ve diğer soketler çalışmaya devam eder. Ancak, bir istemcinin Windows masaüstünde elektrik kesintisi varsa boost::asio::write onlara yazıyor mu, o zaman boost bir sorun algılamıyor ve askıda kalıyor mu boost::asio::write. Bazen yaklaşık 20 dakika askıda kalıyor ve sunucu bu süre zarfında diğer istemcilerle iletişim kuramıyor

Çevrimiçi okuduklarımdan, boost asıo'nun yazarlarının bir zaman aşımı parametresi sunma niyeti yoktur. SO_SNDTİMEO'YU 5 saniyeye ayarlamayı denedim, ancak bunun yazma askıda kalması üzerinde herhangi bir etkisi olmadı. Şu an itibariyle sorunu çözmek için en iyi tahminim, her sokete farklı bir iş parçacığı vermektir, böylece bir istemci diğer istemcileri kaldıramaz. Bundan daha iyi seçenekler var mı? Eğer her soket kendi iş parçacığı ver yaparsam bir ihtiyacım var demek boost::asio::io_context yazma askıda kalmasını önlemek için iş parçacığı başına mı?

Düzenleme: Yorumları gördükten sonra çağıran işlevi yeniden yapmayı denedim boost::asio::write ile boost::asio::async_write. ÖYLE ama yine de basitleştirilmiş bir kod var aşağıda Genel değiştirmek ne gösterir :

Başlangıçta ile 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();
    });
}

İle yeniden 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();
            }
        );
    });
}

Kilit, yalnızca bir çağrıyı garanti etmek için ikinci kodda tanıtıldı boost::asio::async_write bir zamanlar aktifti (bunu yapmanın daha etkili yolları olduğunun farkındayım, ancak bu test için daha basit). Bu kodların her ikisi de, istemci bir elektrik kesintisi olduğunda boost ASIO'YU asmakla aynı soruna sahiptir. Bununla birlikte, farklı şekillerde asılırlar, asenkron kod, asıo'nun diğer eylemleri gerçekleştirmesine izin verir, ancak asılı olan bir hata üretene kadar daha fazla yazmaz

Ayrı bir deney sırasında ayarlamayı denedim SO_KEEPALIVE ancak bu aynı zamanda askıda kalma sorununu da çözmedi

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

En iyi cevabı

1

TCP genellikle böyle çalıştığına ziyaretçi ile aynı fikirdeyim.

Zaman aşımlarını, yuvalarınızdaki zaman uyumsuz işlemleri iptal etmenize izin veren bir ASIO zamanlayıcısı kullanarak girebileceğinizi unutmayın.

Eğer ararsanız birçok örnek var

  • boost:: asıo:: steady_tımer, oost::asıo::high_resolution_timer ve std::chrono saat ailesinin benzer üyeleri
  • boost:: deadline_timer
2021-11-22 22:29:35

Diğer dillerde

Bu sayfa diğer dillerde

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