2013-07-03 2 views
9

मैं हाल ही में अपने आवेदन के साथ एक समस्या ध्यान दिया है और मुझे लगता है कि यह सच है कि मैं boost::asio ठीक से और डॉन 'का उपयोग नहीं करते की वजह से है टी समझ में नहीं आता कि एक टीसीपी संकल्पक क्या करता है।अंतर

मूल रूप से, मैं कनेक्ट करने के लिए एंडपॉइंट प्राप्त करने के लिए boost::asio::ip::tcp::resolver का उपयोग करता हूं।

क्या मैं हाल ही में पता चला कि यह (विशेष रूप से जब मैं स्थानीय होस्ट से कनेक्ट) एक से अधिक endpoint के साथ आ सकते हैं।

फिलहाल मैं सभी अंत बिंदु पर async_connect का अनुरोध करता हूं। मैं 100% निश्चित नहीं हूं लेकिन मुझे लगता है कि यह बुरा है। मुझे एक-एक करके एक async_connect अनुरोध करने के लिए जाना चाहिए, उत्तर के लिए प्रतीक्षा करें और अगर केवल विफल होने पर ही अगले पर प्रयास करें।

तो मूल रूप से जानते हुए भी मैं दो विकल्प हैं कि अगर मैं उन अंतिम बिंदुओं पर async_connect उपयोग करना चाहते हैं:

  1. मेरी कोड refactor ताकि मेरे async_connect संभाल विफलता ठीक से और विफलता पर अन्य उपलब्ध कनेक्ट करने का प्रयास अंत बिंदु। मुझे तब एंडपॉइंट इटरेटर पास करना होगा।

  2. समाधानकर्ता ड्रॉप और एक अंत बिंदु का उपयोग मैं अपने आप को इस तरह का निर्माण: boost::asio::ip::tcp::endpoint("localhost", 20015)

मैं एक तरह से एक लग रहा है कि मैं पहली बार समाधान का उपयोग करना चाहिए और रिसोल्वर स्वयं की तुलना में अधिक कुछ ला रहा है कि है निर्मित एंडपॉइंट।

लेकिन रिज़ॉल्यूवर क्या लाता है, और आत्म निर्मित अंत बिंदु कैसे स्वयं को हल करता है?

उत्तर

11

सैम succinctly दिए जबकि कैसे सबसे अनुप्रयोगों endpoint निर्माण संभाल, मैं resolver उनका विस्तार करना चाहता था।

resolverendpoint (रों) कि परिभाषित अभ्यावेदन के बीच hostname resolution या रूपांतरण के माध्यम से एक पते के लिए संरचित द्विपदीय प्रारूप में शामिल है में एक पते की मानव पठनीय पाठ अभ्यावेदन कन्वर्ट करने के लिए प्रयोग किया जाता है। उदाहरण के लिए, resolver मानव-पठनीय "localhost" से 0x7F000001 को हल कर सकता है या "127.0.0.1" को 0x7F000001 में परिवर्तित कर सकता है। Boost.Asio इस संकल्प को करने के लिए getaddrinfo() का उपयोग या अनुकरण करता है। एसिंक्रोनस रिज़ॉल्यूशन के लिए, ऑपरेशन करने के लिए एक आंतरिक थ्रेड बनाया जाएगा।

दूसरी ओर, basic_endpoint स्वयं को हल नहीं करता है। हालांकि इसे स्ट्रिंग और पोर्ट के साथ नहीं बनाया जा सकता है, इसे ip::address और पोर्ट के साथ बनाया जा सकता है।ip::address बिंदीदार दशमलव के रूप में एक स्ट्रिंग (आईपीवी 4) या हेक्साडेसिमल नोटेशन (IPv6) का निर्माण किया जा सकता है:

namespace ip = boost::asio::ip; 
ip::tcp::endpoint(ip::address::from_string("127.0.0.1"), 20015); 

ip::address::from_string() लिए एक होस्ट नाम प्रदान करना एक अपवाद फेंक देगा: अंत में

namespace ip = boost::asio::ip; 
ip::address::from_string("localhost"); // throws boost::system::system_error 

, उपयोग करें:

  • resolver जब आप होस्टनाम रिज़ॉल्यूशन या आईपी रूपांतरणों का समर्थन करना चाहते हैं। यह विशेष रूप से सुविधाजनक होता है जब आईपी बदल सकते हैं लेकिन होस्टनाम समान रहते हैं, या जब एकल होस्टनाम एकाधिक आईपी को हल कर सकता है। आईपी ​​से पता बनाने के लिए
  • ip::address::from_string()
4

आप सही हैं कि संकल्प ऑपरेशन से लौटे गए सभी एंडपॉइंट्स से कनेक्ट होने की संभावना नहीं है कि आपके आवेदन की अपेक्षा क्या है। चॉइस # 2 काम नहीं करेगा क्योंकि basic_endpoint(const char*, int) के लिए कोई कन्स्ट्रक्टर नहीं है। विकल्प # 1 यह है कि कितने एएसओ उदाहरण संरचित हैं, विशेष रूप से async tcp client demonstrating timeouts

रिज़ॉल्वर से लौटाए गए endpoint_iterator को शामिल करने के लिए अपने कोड को दोबारा सुधारना मुश्किल नहीं होना चाहिए, अगर आपको परेशानी हो तो उपरोक्त उदाहरण का पालन करें। ध्यान दें कि यह अवरुद्ध resolve() का उपयोग करता है और async_resolve() नहीं, अवधारणा वही है।

+1

उत्तर के लिए धन्यवाद, यह बहुत उपयोगी है। मुझे फिर भी पता चला कि एसिंक संकल्प का उपयोग करना अनिश्चित था (मेरा मंच खिड़की है और मुझे अक्सर 'WSA_OPERATION_ABORTED' त्रुटि' 995' मिलती है)। इसलिए मैंने समकालिक समाधान के साथ एक मध्यवर्ती समाधान का चयन किया और प्रत्येक अंत बिंदु पर एक पुनरावर्तक एसिंक्रोनस कनेक्ट किया, और हाँ मेरे कोड को दोबारा सुधारना आसान था। – Arthur