2010-12-06 18 views
10

मेरे पास एक ग्राहक है जो यूडीपी-प्रसारण के माध्यम से डेटा भेजता है। (मान लें कि 127.0.0.255:12345)दो यूडीपी-सर्वर एक ही बंदरगाह पर सुनते हैं?

अब मैं इस डेटा को सुनकर एकाधिक सर्वर रखना चाहता हूं। स्थानीय मशीन पर ऐसा करने के लिए, उन्हें सुनने के लिए पोर्ट 12345 साझा करने की आवश्यकता है।

मेरा प्रश्न यह है कि, यदि यह संभव है, यदि कोई नुकसान है और यदि इस दृष्टिकोण में समस्या हो सकती है।
पंजीकरण प्रक्रिया के कुछ प्रकार लागू:

एक विकल्प है जो दुर्भाग्य से भूमि के ऊपर का एक बहुत साथ लाता है। स्टार्टअप पर, प्रत्येक सर्वर क्लाइंट को अपना पोर्ट बताता है। क्लाइंट प्रत्येक संदेश को संदेश भेजता है (डेटा को कई बार भेजने के लिए, कुछ प्रकार की हैंडशेकिंग लागू करने की आवश्यकता है ...)
क्या आप कोई बेहतर विकल्प जानते हैं?

यदि यह मायने रखता है:
मैं बूस्ट :: असियो के साथ सी ++ का उपयोग कर रहा हूं। सॉफ्टवेयर पोर्टेबल होना चाहिए (मुख्य रूप से लिनक्स और विंडोज)।

+0

मैं बढ़ावा :: asio :: udp :: सॉकेट' set_option (यूडीपी :: सॉकेट :: reuse_address (सही)) से निम्न विधि का उपयोग करने के लिए कोशिश की है इसके बारे में लगभग कोई दस्तावेज नहीं है, क्या किसी के बारे में कोई संकेत है? – MOnsDaR

+1

यह भी देखें http://stackoverflow.com/questions/14388706/ –

उत्तर

5

यह उत्तर cdhowie के उत्तर के संदर्भ में है, जिसने एक दस्तावेज़ को लिंक किया है जिसमें कहा गया है कि SO_REUSEPORT का प्रभाव होगा जो मैं प्राप्त करने की कोशिश कर रहा हूं।

मैंने शोध किया है कि यह विकल्प कैसे लागू किया गया है और मुख्य रूप से बूस्ट :: असियो और लिनक्स पर केंद्रित है।

बूस्ट :: ओएसओ केवल इस विकल्प को सेट करता है यदि ओएस बीएसडी या मैकोज़क्स के बराबर है। उस के लिए कोड फ़ाइल boost/asio/detail/reactive_socket_service.hpp (बूस्ट संस्करण 1.40, नए संस्करणों में, कोड को अन्य फ़ाइलों में स्थानांतरित कर दिया गया है) में निहित है।
मैंने सोचा है कि क्यों एएसओ लिनक्स और विंडोज जैसे प्लेटफॉर्म के लिए इस विकल्प को परिभाषित नहीं करता है।

वहाँ कई पर चर्चा है कि इस लिनक्स में लागू नहीं किया गया संदर्भ हैं: https://web.archive.org/web/20120315052906/http://kerneltrap.org/mailarchive/linux-netdev/2008/8/7/2851754
http://kerneltrap.org/mailarchive/linux-kernel/2010/6/23/4586155

वहाँ भी एक पैच जो कर्नेल को यह कार्यक्षमता जोड़ने चाहिए: https://web-beta.archive.org/web/20110807043058/http://kerneltrap.org/mailarchive/linux-netdev/2010/4/19/6274993

मुझे नहीं पता पता है कि यह विकल्प विंडोज के लिए मौजूद है, लेकिन portable को लिनक्स पर चलने वाले सॉफ़्टवेयर के लिए एक विशेषता के रूप में परिभाषित करके, इसका मतलब है कि SO_REUSEPORT ओएस विशिष्ट है और मेरे प्रश्न के लिए कोई पोर्टेबल समाधान नहीं है।

मैंने जिन चर्चाओं से लिंक किया है उनमें से एक में यूडीपी के लिए एक मास्टर-श्रोता लागू करने की सिफारिश की जाती है जो तब आने वाले डेटा को कई दास-श्रोताओं को प्रदान करती है।

मैं इस उत्तर को स्वीकार्य मानता हूं (हालांकि अपने स्वयं के उत्तर को स्वीकार कर बुरा लगता है), क्योंकि यह इंगित करता है कि पोर्टेबल सॉफ़्टवेयर के साथ इसका उपयोग करने का प्रयास करते समय SO_REUSEPORT का उपयोग करने का दृष्टिकोण विफल हो जाएगा।

+0

तब से लिनक्स को अतिरिक्त सुविधा मिली (कर्नेल 3.9 के बाद से)। यहां दिलचस्प जानकारी देखें: http://lwn.net/Articles/542629/ - हालांकि, 'SO_REUSEPORT' का अर्थ है कि एकाधिक सर्वर डेटाग्राम स्वीकार कर सकते हैं, न कि वे सभी एक ही डेटाग्राम प्राप्त करते हैं। –

22

आपको SO12USEPORT विकल्प के साथ दोनों प्रक्रियाओं में सॉकेट को बांधना होगा। यदि आप पहली बार इस विकल्प को निर्दिष्ट नहीं करते हैं, तो दूसरे में बाध्यकारी विफल हो जाएगा। इसी प्रकार, यदि आप पहले में यह विकल्प निर्दिष्ट करते हैं लेकिन दूसरा नहीं, तो दूसरे में बाध्यकारी असफल हो जाएगा। यह विकल्प प्रभावी रूप से दोनों अनुरोधों को निर्दिष्ट करता है ("मैं इस बंदरगाह से बांधना चाहता हूं भले ही यह पहले से ही किसी अन्य प्रक्रिया से बंधे हों") और एक अनुमति ("अन्य प्रक्रियाएं भी इस बंदरगाह से बंधी जा सकती हैं")।

अधिक जानकारी के लिए this document के अनुभाग 4.12 देखें।

+0

मैंने इस उत्तर को "सही" के रूप में चिह्नित किया क्योंकि यह दिखाता है कि एक ही समय में सेरवाल सर्वर के साथ 1 पोर्ट को सुनना संभव नहीं है। लिंक किया गया यूआरएल इस उत्तर का समर्थन करता है। यदि कोई अन्य उत्तर पोस्ट किया गया है जो दिखाता है कि यह संभव है या जिसकी अधिक डिस्काउंट स्पष्टीकरण है, तो मैं इसके बजाय नए उत्तर को स्वीकार कर दूंगा। – MOnsDaR

+1

@MOnsDaR: आपका क्या मतलब है "संभव नहीं है?" उस दस्तावेज़ से: * "SO_REUSEPORT ध्वज एकाधिक प्रक्रियाओं को एक ही पते से जुड़ने की अनुमति देता है बशर्ते वे सभी SO_REUSEPORT विकल्प का उपयोग करें।" * – cdhowie

+2

यह इस तरह के कुछ भी नहीं दिखाता है। यह दिखाता है कि यह * संभव है और यह दिखाता है * कैसे। * – EJP

3

कई स्रोत बताते हैं कि आपको विंडोज़ पर SO_REUSEADDR का उपयोग करना चाहिए। लेकिन कोई भी उल्लेख नहीं करता कि के साथ सॉकेट बाध्यकारी के साथ यूडीपी संदेश प्राप्त करना संभव है। नीचे दिया गया कोड सॉकेट को स्थानीय listen_endpoint पर बाध्य करता है, यह आवश्यक है, क्योंकि इसके बिना आप अभी भी अपने यूडीपी संदेशों को प्राप्त कर सकते हैं और फिर भी प्राप्त करेंगे, लेकिन डिफ़ॉल्ट रूप से आपके पास पोर्ट का अनन्य स्वामित्व होगा।

हालांकि यदि आप सॉकेट पर (या टीसीपी का उपयोग करते समय स्वीकार्य पर) reuse_address (true) सेट करते हैं, और सॉकेट को बाद में बांधते हैं, तो यह कई अनुप्रयोगों को सक्षम करेगा, या आपके आवेदन के कई उदाहरण इसे फिर से करने के लिए सक्षम करेगा, और सभी को सभी संदेश प्राप्त होंगे। कोई सफलता के साथ `... नहीं है;

// Create the socket so that multiple may be bound to the same address. 
boost::asio::ip::udp::endpoint listen_endpoint(
    listen_address, multicast_port); 

// == important part == 
socket_.open(listen_endpoint.protocol()); 
socket_.set_option(boost::asio::ip::udp::socket::reuse_address(true)); 
socket_.bind(listen_endpoint); 
// == important part == 

boost::array<char, 2000> recvBuffer; 
socket_.async_receive_from(boost::asio::buffer(recvBuffer), m_remote_endpoint, 
     boost::bind(&SocketReader::ReceiveUDPMessage, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred) 
संबंधित मुद्दे