2009-04-15 11 views
5

मैं सी ++ में कुछ सॉकेट नेटवर्क प्रोग्रामिंग का उपयोग करने की कोशिश कर रहा हूं। मैं पाठ "हैलो वर्ल्ड" भेजने की कोशिश कर रहा हूं! C++ भेजें() फ़ंक्शन का उपयोग कर सर्वर पर। सबसे पहले, मैंने बफर को 13 के आकार में सेट किया है क्योंकि "हैलो वर्ल्ड!" पूरी तरह से 12 वर्ण हैं (आपको इसे चरित्र गणना से अधिक बनाना है)। प्रेषण फ़ंक्शन केवल वर्णों को सर्वर पर भेजता है यदि मैं इसे लगभग 7 बार भेजता हूं। और जब यह सर्वर पर आता है तो यह इस तरह दिखता है:सी ++ सॉकेट 256 बाइट बफर

"हैलो वर्ल्ड! हैलो वर्ल्ड! हैलो वर्ल्ड! हैलो वर्ल्ड! हैलो वर्ल्ड! हैलो वर्ल्ड! हैलो वर्ल्ड!"

अब यहां मजाकिया हिस्सा है। "हैलो वर्ल्ड!" अगर मैं बफर आकार 256 (चार बफर [256];) पर सेट करता हूं तो वाक्य तुरंत भेजता है। जब सर्वर की बात आती है, तो यह "हैलो वर्ल्ड!" दिखाता है दो शब्दों के बाद अंतरिक्ष के पूरे समूह के साथ। यह क्यों हो रहा है और यदि संभव हो, तो मैं इसे कैसे ठीक कर सकता हूं? कृपया मुझे बताओ।

धन्यवाद

+0

क्या आपने अपनी स्ट्रिंग को समाप्त कर दिया था? "हैलो वर्ल्ड! \ 0" – Alan

उत्तर

7

जब आप अपने बफर के साथ read (या receive) फोन सॉकेट से पढ़ने के लिए, एक पूर्णांक मान दिया जाता है कि पढ़े गए बाइट की संख्या निर्दिष्ट करता है। आपको केवल बफर से इतना लेना चाहिए। बाकी अप्रासंगिक है:

int count = read(...); 
// buffer[0 .. count - 1] contains the appropriate data. 
+0

और बस आपको यह बताने के लिए, डेटा प्राप्त करने वाला सर्वर सी # – QAH

+0

क्यूएएच में बनाया गया है: यह सी # सॉकेट, सॉकेट के लिए भी सच है। रिसीव विधि। –

4

बफर तब तक डेटा स्टोर करने के लिए मौजूद हैं जब तक कि आप इसे भेजने के लिए तैयार न हों। आपके पास 256 का प्रेषण बफर आकार है। बफर के माध्यम से 256 वर्ण प्रेषित नहीं होते हैं, तब तक आपका डेटा दूसरी तरफ नहीं भेजा जाएगा। जब आप जानते हैं कि आप भेजने के लिए तैयार हैं तो आप अपने बफर पर फ्लश विधि को कॉल करके इसे ठीक कर सकते हैं।

स्पष्ट होने के लिए, आप आंतरिक रूप से बफरिंग कर रहे हैं, फिर ओएस (या लाइब्रेरी) दोबारा बफर कर रहा है जब आप भेजते हैं() और कुछ डेटा पास करते हैं।

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

वैकल्पिक रूप से, यदि आप * निक्स में हैं, तो बस नागल के एल्गोरिदम को बंद करें ताकि ओएस आपके छोटे पैकेट को बफर न करे। या, जब आप सॉकेट सेट करते हैं, तो TCP_NODELAY विकल्प

6

का उपयोग करना सुनिश्चित करें, आमतौर पर नागल का एल्गोरिदम डिफ़ॉल्ट रूप से चालू होता है। यह कई छोटे पैकेट को एक में जोड़ देगा। नागल के एल्गोरिदम को बंद करने से छोटे पैकेट तुरंत भेजे जाएंगे।

0

मान लीजिए कि यह एक सॉक्रम्रीम सॉकेट है, यह जानना महत्वपूर्ण बात यह है कि अंतर्निहित टीसीपी प्रोटोकॉल किसी सेगमेंट सीमाओं को बनाए रखता नहीं है। यही है, जब आप कई बार भेजें() को कॉल करते हैं, तो आपके द्वारा भेजे गए सभी डेटा को दूसरी तरफ एक एकल आरईवी() कॉल द्वारा आसानी से वापस किया जा सकता है। या, एक प्रेषण() कॉल में भेजा गया डेटा दूसरे छोर पर कई recv() s में वापस किया जा सकता है, उदा। यदि नेटवर्क की भीड़ के कारण कुछ पैकेट देरी हो गई हैं। यह टीसीपी के डिजाइन के लिए मौलिक है, और आपके आवेदन को तदनुसार डिजाइन किया जाना चाहिए।

इसके अलावा, जैसा कि मेहदद द्वारा उल्लेख किया गया है, आरईवी() कॉल तार से पढ़े गए बाइट्स की संख्या देता है। बफर में उस बिंदु के बाद कुछ भी कचरा है, और डेटा शून्य-समाप्त नहीं है।

एक SOCK_DGRAM सॉकेट नीचे यूडीपी का उपयोग करता है, जो पूरी तरह से पैकेट उन्मुख है, टीसीपी जैसे धारा-उन्मुख के विपरीत। हालांकि, यूडीपी विश्वसनीयता की गारंटी नहीं देता है (यू अविश्वसनीय के लिए खड़ा है), इसलिए आपको खोए, डुप्लिकेट, आउट-ऑफ-ऑर्डर इत्यादि को पैकेट स्वयं को संभालना होगा। यह धारा-उन्मुख I/O से बहुत कठिन है।

+0

यूडीपी उपयोगकर्ता डेटाग्राम प्रोटोकॉल है - इसमें इसके नाम पर अविश्वसनीय नहीं है। आप सही हैं कि यह अपेक्षाकृत अविश्वसनीय है, हालांकि :) –

0

सॉकेट प्रोग्रामिंग कठिन, त्रुटि प्रवण और गैर पोर्टेबल है।Boost या ACE जैसे पुस्तकालयों का उपयोग करना शुरू करें जो आपको निम्न स्तर सी एपीआई से ढालते हैं और आपको प्लेटफॉर्म स्वतंत्र अबास्ट्रक्शन प्रदान करते हैं।