मैं एक सर्वर अनुप्रयोग का उपयोग करता है कि को बढ़ावा देने ASIO संवाद करने के लिए कई ग्राहकों के साथ. सर्वर आवेदन पर चलाता है एक Linux सर्वर और क्लाइंट पर चलाने के लिए Windows डेस्कटॉप.
वर्तमान डिजाइन बहु लड़ी पिरोया हालांकि वहाँ केवल एक को बढ़ावा देने ASIO thead (जो चलाता है boost::asio::io_context
). को बढ़ावा देने के ASIO धागे के लिए ही जिम्मेदार है, पढ़ने, लिखने, और कुछ निराला तक प्रेषण. पढ़ने का उपयोग किया जाता है boost::asio::async_read
लेकिन प्रतियां जिसके परिणामस्वरूप संदेश इतना है कि एक धागे के काम कर सकते हैं प्रसंस्करण. लेखन का उपयोग किया जाता है boost::asio::write
लेकिन संदेश पहले से ही किया गया है की नकल की और हाथ बंद करने के लिए बढ़ावा देने के ASIO धागा
अधिकांश परिस्थितियों में, जब एक क्लाइंट डिस्कनेक्ट बढ़ावा ASIO एक त्रुटि फेंकता है, मैं शट डाउन जुड़े, सॉकेट, और अन्य कुर्सियां रखने के लिए काम कर रहा है । लेकिन अगर एक ग्राहक के विंडोज डेस्कटॉप के लिए एक बिजली की विफलता है, जबकि boost::asio::write
के लिए लिख रहा है तो उन्हें बढ़ावा नहीं करता है का पता लगाने के लिए एक मुद्दा है और में लटकी हुई है boost::asio::write
. यह लटकी हुई है के लिए लगभग 20 मिनट के लिए कभी कभी और सर्वर संवाद नहीं कर सकता अन्य ग्राहकों के साथ इस समय के दौरान
से मैं क्या पढ़ा है, ऑनलाइन लेखकों को बढ़ावा देने के ASIO का कोई इरादा नहीं है शुरू करने के लिए एक मध्यांतर पैरामीटर । मैं स्थापित करने की कोशिश की SO_SNDTIMEO करने के लिए 5 सेकंड है, लेकिन नहीं था कि किसी को प्रभावित पर लिखने लटका. अब के रूप में मेरा सबसे अच्छा लगता है करने के लिए इस मुद्दे को हल करने के लिए है प्रत्येक सॉकेट एक अलग धागा इतना है कि एक ग्राहक नहीं कर सकते नीचे ले अन्य ग्राहकों. वहाँ किसी भी बेहतर विकल्प की तुलना में यह? अगर मैं दे हर सॉकेट अपने स्वयं के धागे करता है कि मतलब है कि मैं एक की आवश्यकता होगी boost::asio::io_context
प्रति धागे से बचने के लिए लिखने लटका?
संपादित करें: देखने के बाद टिप्पणी की कोशिश की redoing कि समारोह कॉल boost::asio::write
के साथ boost::asio::async_write
. नीचे मैं कुछ कोड है कि सरलीकृत किया गया था के लिए तो, लेकिन अभी भी पता चलता है क्या के समग्र परिवर्तन किया गया था:
मूल रूप से के साथ 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();
});
}
Redone के साथ 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();
}
);
});
}
ताला में पेश किया गया था दूसरी कोड की गारंटी करने के लिए केवल एक ही कॉल करने के लिए boost::asio::async_write
सक्रिय था पर एक समय (मैं जानता हूँ कि वहाँ रहे हैं और अधिक performant तरीके से ऐसा करने के लिए, लेकिन यह आसान है के लिए परीक्षण). इन दोनों के कोड है एक ही मुद्दे की फांसी को बढ़ावा देने ASIO जब ग्राहक एक बिजली की विफलता. हालांकि वे लटका है, अलग अलग तरीकों से अतुल्यकालिक कोड की अनुमति देता है को बढ़ावा देने के लिए ASIO करने के लिए अन्य कार्यों प्रदर्शन नहीं है, बस आगे लिखते हैं जब तक फांसी से एक पैदा करता है, एक त्रुटि
के दौरान एक अलग प्रयोग मैंने किया था स्थापित करने की कोशिश करो SO_KEEPALIVE
लेकिन जो भी समाधान नहीं किया फांसी का मुद्दा