2009-03-24 13 views
8

मैं लिनक्स सॉकेट का उपयोग कर सी ++ में क्लाइंट-सर्वर जोड़ी लिख रहा हूं। मैं चाहता हूं कि सर्वर कनेक्शन के लिए सुनें, और एक क्लाइंट कनेक्ट होने पर सर्वर को कनेक्ट करने का प्रयास करने वाले किसी अन्य क्लाइंट को अस्वीकार कर देना चाहिए।मैं एक टीसीपी सर्वर कैसे बना सकता हूं जो एक समय में केवल एक कनेक्शन स्वीकार करेगा?

मैंने listen फ़ंक्शन में 0 और 1 तक बैकलॉग पैरामीटर सेट करके इसे कार्यान्वित करने का प्रयास किया और न तो इनमें से कोई भी मान काम करता प्रतीत होता है। पहला क्लाइंट अपेक्षित के रूप में जुड़ता है, लेकिन किसी भी बाद के क्लाइंट बस क्लाइंट खत्म होने पर ही ब्लॉक करते हैं। मेरे लिए वास्तव में भ्रमित करने वाला यह है कि वे सर्वर से कनेक्ट करने से अवरुद्ध नहीं होते हैं, वे पहले पढ़ने पर अवरुद्ध होते हैं।

मैं the code here इस्तेमाल किया मेरे क्लाइंट और सर्वर लेखन आरंभ करने के लिए। क्या किसी को पता है कि सर्वर को केवल एक क्लाइंट कनेक्शन स्वीकार करने के लिए बदलने की आवश्यकता है, और बाद के कनेक्शन प्रयासों को छोड़ दें?

उत्तर

7

जब आप कोई कनेक्शन स्वीकार करते हैं, तो एक नई सॉकेट बन जाती है। पुराना अभी भी भविष्य के कनेक्शन सुनने के लिए उपयोग किया जाता है।

जब से तुम एक बार में केवल 1 कनेक्शन की अनुमति देना चाहते, तो आप सिर्फ कनेक्शन स्वीकार कर सकता है, और फिर नए स्वीकृत सॉकेट बंद अगर आप आप पहले से ही एक और कार्रवाई कर रहे हैं का पता लगाने।

वहाँ एक शुद्ध अंतर यह है कि आप सही होने के बाद स्वीकार नई स्वीकार किए जाते हैं सॉकेट बंद करने की तुलना में देख रहे है? जैसे ही ग्राहक अपनी सॉकेट का उपयोग करने की कोशिश करता है (या तुरंत अगर यह पहले से ही कॉल पर सर्वर पर इंतजार कर रहा है) की आखिरी त्रुटि के साथ: सर्वर सक्रिय रूप से कनेक्शन बंद कर देता है।

+0

मैं यह देखने के लिए अपना कोड संशोधित कर रहा हूं कि मैं यह कर सकता हूं या नहीं। मैं आपसे वापस आऊंगा ... –

+0

+1 ठीक वही है जो मैं सुझाव देने वाला था। –

+0

जाने का एक अच्छा तरीका लगता है! टी.के.एस! – LeoPucciBr

4

बस नहीं fork()accept() के बाद करते हैं।

यह छद्म सी-कोड केवल एक बार में एक ग्राहक को स्वीकार करेंगे।

while(1) { 
    listen() 
    accept() 
    *do something with the connection* 
    close() 
} 
+1

मैं फोर्क नहीं()। उदाहरण एक साधारण गूंज सर्वर है जो अनुरोध को संसाधित करता है। –

3

आप अपना मूल सॉकेट बंद कर सकते हैं जो पहले कनेक्शन को स्वीकार करने के बाद कनेक्शन सुन रहा है। मुझे नहीं पता कि आप जिस सॉकेट क्लास का उपयोग कर रहे हैं वह आपको ऐसा करने की अनुमति देगा।

+0

यह एक विचार है, लेकिन मैं इसे पहले कनेक्शन के बाद नए कनेक्शन स्वीकार करना चाहता हूं। –

+0

@ बिल, फिर जब आप फिर से कनेक्शन स्वीकार करने के लिए तैयार हों तो सॉकेट को फिर से खोलें। –

3

लगता है जैसे आपको इसे मैन्युअल रूप से कार्यान्वित करने की आवश्यकता है। क्लाइंट को कनेक्ट करने दें, फिर सर्वर से क्लाइंट को एक डिस्कनेक्ट संदेश भेजें यदि पहले से ही कोई अन्य ग्राहक जुड़ा हुआ है। अगर क्लाइंट को यह संदेश प्राप्त होता है तो इसे अपने आप डिस्कनेक्ट कर दें।

0

यदि आपके पास ग्राहकों पर नियंत्रण है, तो आप सॉकेट को गैर-अवरुद्ध कर सकते हैं। इस मामले में वे त्रुटि संदेश EINPROGRESS वापस कर देंगे।

मैं अभी भी कैसे सॉकेट बदलने के लिए गैर अवरुद्ध होने के लिए देख रहा हूँ। अगर कोई जानता है कि कैसे बंद करना है, तो जवाब को संपादित करने में संकोच न करें।

0

एक नया कनेक्शन स्वीकार करने और शुरू करने के बाद सुनना सॉकेट मरने दें। फिर जब वह कनेक्शन किया जाता है, तो क्या यह एक नई सुनवाई सॉकेट को घुमाएगा।

 
TCP_DEFER_ACCEPT (since Linux 2.4) 
    Allows a listener to be awakened only when data arrives on the socket. 
    Takes an integer value (seconds), this can bound the maximum number of 
    attempts TCP will make to complete the connection. This option should 
    not be used in code intended to be portable. 

मैं इसे प्रभाव आप वर्णित करने के लिए नेतृत्व करेंगे, कि जोड़ने ग्राहक connect पर ब्लॉक नहीं करता ग्रहण करेंगे, लेकिन पर:

0

आप आपके सुनने सॉकेट पर सॉकेट विकल्प TCP_DEFER_ACCEPT सेट हो सकता है बाद में read।मैं बिल्कुल यकीन है कि क्या विकल्प डिफ़ॉल्ट सेटिंग है और क्या यह इस व्यवहार को निष्क्रिय करने के लिए सेट किया जाना चाहिए करने के लिए, लेकिन शायद शून्य का एक मूल्य एक कोशिश के लायक है नहीं कर रहा हूँ:

int opt = 0; 
setsockopt(sock, IPPROTO_TCP, TCP_DEFER_ACCEPT, &opt, sizeof(opt)); 
+0

मैं एक समय में केवल एक कनेक्शन की अनुमति देने के लिए देख रहा हूं। मैंने उपरोक्त वर्णित 'सेटॉकॉप्टी 'का उपयोग करने का प्रयास किया: ' int opt ​​= 0; setsockopt (जुर्राब, IPPROTO_TCP, TCP_DEFER_ACCEPT, और चुनते हैं, sizeof (ऑप्ट)); ' लेकिन यह काम नहीं किया। इसलिए मैंने 1 को 'ऑप्ट' सेट किया और कोशिश की और यह अभी भी काम नहीं कर सका। क्या कोई चेक है जिसे हमें 'sizeof (opt)' पर करने की आवश्यकता है? –

1

के बाद से आप केवल 1 अनुमति देना चाहते हैं एक समय में कनेक्शन, आप केवल कनेक्शन स्वीकार कर सकते हैं, और फिर नए स्वीकृत सॉकेट को बंद कर सकते हैं यदि आप पाते हैं कि आप पहले से ही किसी अन्य प्रसंस्करण कर रहे हैं।

मुझे लगता है कि यह बंद होने वाली सुनो सॉकेट होना चाहिए। जब पहला कनेक्शन स्थापित होता है, तो आप मूल सुनो सॉकेट बंद कर देते हैं। और उसके बाद कोई और कनेक्शन स्थापित नहीं किया जा सकता है।

पहले कनेक्शन समाप्त होने के बाद, आप फिर से सुनने के लिए एक नई सॉकेट बना सकते हैं।

0

जहाँ तक मैं देखता हूं, बिल्कुल एक कनेक्शन सुनना संभव नहीं है।

टीसीपी में 3-तरफा हैंडशेक शामिल है। पहले syn पैकेट प्राप्त होने के बाद कर्नेल एक प्रतीक्षा कतार में "कनेक्शन" रखता है, syn/ack के साथ उत्तर देता है और अंतिम ack के लिए प्रतीक्षा करता है। इसे प्राप्त करने के बाद यह प्रतीक्षा कतार से कनेक्शन कतार में कनेक्शन को स्थानांतरित करता है, जहां इसे accept() कॉल का उपयोग करके एप्लिकेशन द्वारा उठाया जा सकता है। (विवरण के लिए here देखें।)

लिनक्स पर बैकलॉग तर्क केवल स्वीकृति कतार के आकार को सीमित करता है। लेकिन कर्नेल अभी भी 3-तरफा हैंडशेक जादू करेगा। क्लाइंट को अंतिम एके के साथ syn/ack और उत्तर प्राप्त होते हैं और कनेक्शन स्थापित किए जाते हैं।

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

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

संबंधित मुद्दे