Boost.Asio दस्तावेज से आपके द्वारा उल्लेख किए जाने वाले उदाहरण वास्तव में यह देखने के लिए बहुत अच्छे हैं कि चीजें कैसे काम करती हैं। आप सही हैं कि पहले इसे समझना थोड़ा मुश्किल लग सकता है, खासकर यदि आप इन अवधारणाओं के लिए नए हैं। हालांकि, मैं अनुशंसा करता हूं कि आप चैट सर्वर उदाहरण से शुरू करें और इसे अपनी मशीन पर बनाया जाए। इससे आपको यह जानने के लिए चीजों को देखने और चीजों को बदलने शुरू करने की अनुमति मिल जाएगी। मुझे कुछ चीजों के माध्यम से आपको मार्गदर्शन करने दें जो मुझे शुरू करने के लिए महत्वपूर्ण लगता है।
अपने विवरण से आप जो करना चाहते हैं, ऐसा लगता है कि चैट सर्वर आपको एक अच्छा प्रारंभिक बिंदु देता है क्योंकि आपके पास पहले से ही समान टुकड़े हैं। सर्वर एसिंक्रोनस होने के नाते आप जो चाहते हैं वह एक ही थ्रेड के साथ कई क्लाइंट को आसानी से संभाल सकता है। शुरुआत से कुछ भी जटिल नहीं है।
सरलीकृत, इस मामले में एसिंक्रोनस का मतलब है कि आपका सर्वर एक कतार बंद कर देता है, एक हैंडलर (कार्य) लेता है और इसे निष्पादित करता है। अगर कतार पर कुछ भी नहीं है, तो यह कतार पर कुछ लगाने के लिए इंतजार कर रहा है। आपके मामले में इसका मतलब है कि यह किसी ग्राहक से कनेक्ट हो सकता है, किसी ग्राहक से संदेश का एक नया पठन या ऐसा कुछ। इसके लिए काम करने के लिए, प्रत्येक हैंडलर (किसी विशेष घटना पर प्रतिक्रिया को संभालने वाला फ़ंक्शन) स्थापित करने की आवश्यकता होती है।
मुझे चैट सर्वर उदाहरण से कोड का उपयोग करके थोड़ा सा समझाएं।
server source file में, आप chat_server
कक्षा देखें जो कन्स्ट्रक्टर में start_accept
पर कॉल करता है। यहां स्वीकार हैंडलर स्थापित हो जाता है।
void start_accept()
{
chat_session_ptr new_session(new chat_session(io_service_, room_)); // 1
acceptor_.async_accept(new_session->socket(), // 2
boost::bind(&chat_server::handle_accept, this, new_session, // 3
boost::asio::placeholders::error)); // 4
}
पंक्ति 1: एक chat_session
वस्तु जो एक ग्राहक और सर्वर के बीच एक सत्र का प्रतिनिधित्व करता बनाई गई है। स्वीकृति के लिए एक सत्र बनाया गया है (कोई क्लाइंट अभी तक कनेक्ट नहीं हुआ है)।
पंक्ति 2: एक अतुल्यकालिक सॉकेट के लिए स्वीकार करते हैं ...
लाइन 3: ... chat_server::handle_accept
कॉल करने के लिए जब ऐसा होता है बाध्य। सत्र को पहले क्लाइंट द्वारा उपयोग किए जाने के साथ पास किया जाता है जो कनेक्ट करता है।
अब, अगर हम handle_accept
देखते हैं तो हम देखते हैं कि क्लाइंट कनेक्ट पर, start
सत्र के लिए कहा जाता है (यह केवल सर्वर और इस क्लाइंट के बीच सामान शुरू करता है)।आखिर में अन्य ग्राहक भी कनेक्ट करना चाहते हैं, तो एक नई स्वीकृति बकाया है।
void handle_accept(chat_session_ptr session,
const boost::system::error_code& error)
{
if (!error)
{
session->start();
}
start_accept();
}
यही वह है जो आप चाहते हैं। आने वाले कनेक्शन के लिए एक उत्कृष्ट स्वीकृति। और यदि एकाधिक ग्राहक कनेक्ट हो सकते हैं, तो हमेशा इन बकाया में से एक होना चाहिए ताकि सर्वर स्वीकृति को संभाल सके।
सर्वर और क्लाइंट इंटरैक्ट कैसे सत्र में हैं और आप उसी डिजाइन का पालन कर सकते हैं और जो भी आप चाहते हैं उसे संशोधित कर सकते हैं। आप उल्लेख करते हैं कि सर्वर को क्या भेजा जाता है और विभिन्न चीजें करने की आवश्यकता होती है। chat_session
और start
फ़ंक्शन पर एक नज़र डालें जिसे सर्वर द्वारा handle_accept
में बुलाया गया था।
void start()
{
room_.join(shared_from_this());
boost::asio::async_read(socket_,
boost::asio::buffer(read_msg_.data(), chat_message::header_length),
boost::bind(
&chat_session::handle_read_header, shared_from_this(),
boost::asio::placeholders::error));
}
boost::asio::async_read
पर कॉल करना महत्वपूर्ण है। यह वही है जो आप चाहते हैं। यह सॉकेट पर एक उत्कृष्ट पढ़ने देता है, इसलिए सर्वर क्लाइंट भेजता है जो पढ़ सकता है। एक हैंडलर (फ़ंक्शन) है जो इस घटना chat_session::handle_read_header
से जुड़ा हुआ है। जब भी सर्वर सॉकेट पर कुछ पढ़ता है तो इसे कॉल किया जाएगा। इस हैंडलर फ़ंक्शन में आप यह निर्धारित करने के लिए अपना विशिष्ट कोड डालना शुरू कर सकते हैं कि एक विशिष्ट संदेश भेजा गया है और इसी तरह क्या करना है।
यह जानना महत्वपूर्ण है कि जब भी इन एसिंक्रोनस बूस्ट को कॉल किया जाता है :: एएसओ फ़ंक्शन चीजें उस कॉल के भीतर नहीं होतीं (यानी यदि आप फ़ंक्शन को पढ़ते हैं तो सॉकेट पढ़ा नहीं जाता है)। यह असीमित पहलू है। आप बस कुछ के लिए हैंडलर पंजीकृत करते हैं और ऐसा होने पर आपके कोड को वापस बुलाया जाता है। इसलिए, जब इसे पढ़ा जाता है तो यह तुरंत वापस आ जाएगा और आप सर्वर के लिए handle_accept
में वापस आ गए हैं (यदि आप अनुसरण करते हैं कि चीजें कैसे कॉल की जाती हैं)। और यदि आपको याद है तो हम एक और एसिंक्रोनस स्वीकृति सेट अप करने के लिए start_accept
पर भी कॉल करते हैं। इस बिंदु पर आपके पास दो उत्कृष्ट हैंडलर हैं जो किसी अन्य क्लाइंट को कनेक्ट करने या पहले क्लाइंट को कुछ भेजने के लिए इंतजार कर रहे हैं। पहले क्या होता है इसके आधार पर, उस विशिष्ट हैंडलर को बुलाया जाएगा।
यह भी समझना महत्वपूर्ण है कि जब भी कुछ चल रहा है, तब तक यह निर्बाध हो जाएगा जब तक कि उसे करने की आवश्यकता नहीं होती है। अन्य हैंडलर को तब भी इंतजार करना पड़ता है जब बकाया घटनाएं होती हैं जो उन्हें ट्रिगर करती हैं।
अंत में, सर्वर चलाने के लिए आपको io_service
की आवश्यकता होगी जो असियो में एक केंद्रीय अवधारणा है।
io_service.run();
यह एक लाइन आप main
समारोह में देखते हैं। यह सिर्फ इतना कहता है कि थ्रेड (उदाहरण में केवल एक) को io_service चलाया जाना चाहिए, जो कि कतार है जहां काम करने के लिए हैंडलर लगाए जाते हैं। कुछ भी नहीं होने पर, io_service बस प्रतीक्षा करता है (निश्चित रूप से मुख्य धागे को अवरुद्ध करता है)।
मुझे उम्मीद है कि यह आपको जो करना है, उसके साथ शुरू करने में आपकी सहायता करता है। ऐसी कई चीजें हैं जो आप कर सकते हैं और सीखने के लिए चीजें हैं। मुझे यह सॉफ्टवेयर का एक बड़ा टुकड़ा मिल गया है! सौभाग्य!
चीयर्स धन्यवाद। आप सही हैं, मुझे वास्तव में उनके माध्यम से काटने की ज़रूरत है। एक बात जो मैं समझ नहीं पा रहा हूं वह उदाहरणों में साझा पॉइंटर्स का मजबूत उपयोग है। वे कहाँ रखा जाता है? जादूगर के रूप में जादूगर के अंदर? यदि कनेक्शन मर जाता है, तो क्या वे स्वचालित रूप से साफ हो जाएंगे? धन्यवाद – Cookie
साझा पॉइंटर्स का उपयोग कुछ वस्तुओं को हैंडलर के अंदर "अंदर" रखने के लिए है। असियो में केवल हैंडलर है (फ़ंक्शन :: बाइंड से प्राप्त हुआ है) और साझा पॉइंटर वहां बाध्य है। इस तरह साझा पॉइंटर में ऑब्जेक्ट तब तक जीवित रखा जाता है जब तक कि हैंडलर जीवित रहता है, जो महत्वपूर्ण है। सत्र सत्र में साझा_फ्रॉम_थिस() के रूप में सत्र को सभी बूस्ट :: बाइंड के रूप में पारित किया जाता है, जो आप देखते हैं, जो कि जीवन भर के रूप में काफी अच्छा है, उसके बाद हर समय एसिंक्रोनस हैंडलर का स्वामित्व होता है, जो हाँ के मामले में सफाई को संभालेगा त्रुटि। – murrekatt