2010-05-11 5 views
24

हम नेट और सॉकेट का उपयोग कर रहे हैं। सर्वर सॉकेट सेंडर (बाइट्स []) विधि का उपयोग कर रहा है, इसलिए यह सिर्फ पूरे पेलोड भेजता है। दूसरी तरफ हम ग्राहक डेटा ले रहे हैं। Socket.Receive (बफ़र [])। माइक्रोसॉफ्ट (और अन्य) के सभी उदाहरणों में वे 8192 के बफर आकार के साथ चिपके हुए प्रतीत होते हैं। हमने इस आकार का उपयोग किया है, लेकिन हर बार और फिर हम उन ग्राहकों को डेटा भेज रहे हैं जो इस बफर आकार से अधिक हैं।सॉकेट प्रोग्रामिंग के लिए एक अच्छा बफर आकार क्या है?

क्या यह निर्धारित करने का कोई तरीका है कि सर्वर की भेजे गए तरीके ने हमें कितना डेटा भेजा है? सबसे अच्छा बफर आकार क्या है?

उत्तर

31

भले ही आप उससे अधिक डेटा भेज रहे हों, फिर भी यह प्राप्त करने के लिए एक कॉल में उपलब्ध नहीं हो सकता है।

आप यह निर्धारित नहीं कर सकते कि सर्वर ने कितना डेटा भेजा है - यह स्ट्रीम डेटा है, और आप एक समय में केवल टुकड़े पढ़ रहे हैं। आप एक संदेश में भेजे गए सर्वर के भाग पढ़ सकते हैं, या आप एक प्राप्त कॉल में कॉल भेजें दो से डेटा पढ़ सकते हैं। 8K एक उचित बफर आकार है - इतना बड़ा नहीं है कि आप बहुत सारी मेमोरी बर्बाद कर देंगे, और इतनी छोटी नहीं कि आपको बर्बाद भारों का उपयोग करना होगा। 4K या 16K काफी संभवतः ठीक भी होगा ... मैं व्यक्तिगत रूप से नेटवर्क बफर के लिए 16K से ऊपर नहीं जाना शुरू करूंगा - मुझे संदेह है कि आप शायद ही कभी उन्हें भरें।

आप एक बहुत बड़े बफर का उपयोग और लॉग कितने बाइट्स प्रत्येक कॉल में प्राप्त हुए थे करने के लिए कोशिश कर रहा द्वारा प्रयोग सकता है - यह है कि आप कितना आम तौर पर उपलब्ध है के कुछ विचार देना होगा - लेकिन यह वास्तव में असर नहीं दिखा होगा एक छोटे बफर का उपयोग करने के लिए। 8K बफर का उपयोग करने पर आपके पास क्या चिंताएं हैं? यदि यह प्रदर्शन है, तो क्या आपके पास कोई सबूत है कि आपके कोड का यह पहलू एक प्रदर्शन बाधा है?

+0

यदि यह सब संभव हो तो मैं बफर आकार को बढ़ाना चाहता हूं। हम इसे 32K बनाने के बारे में सोच रहे थे, लेकिन मैं उपरोक्त परिदृश्य के बारे में चिंतित था जहां मुझे प्राप्त आदेश कमांड नहीं मिलेगा, भले ही मैंने इसे एक ही प्रेषण में भेजा हो। – uriDium

+0

क्षमा करें मैं यह उल्लेख करना भूल गया कि हम इसे ब्लॉकिंग मोड में कर रहे हैं। हालांकि मुझे यह कोई फर्क नहीं पड़ता है। – uriDium

+3

@uriDium: आपको अपना कोड लिखना चाहिए ताकि यह एक प्राप्त में एक ही भेजें से सब कुछ प्राप्त करने पर भरोसा न करे। यह मॉडल नहीं है कि टीसीपी उपयोग करता है - यह एक * स्ट्रीम * मॉडल है। यदि आप उस स्ट्रीम को अलग-अलग संदेशों में विभाजित करना चाहते हैं, तो आपको या तो एक डिलीमीटर का उपयोग करना चाहिए या प्रत्येक संदेश के लिए लम्बाई उपसर्ग लिखना चाहिए ताकि क्लाइंट को कितना पढ़ना पड़े। –

1

8192 आदर्श होगा। यदि आपके पास इस आकार से अधिक डेटा है, तो यह आपके लिए निरंतर लंबाई पैकेट में डेटा भेजने के लिए बेहतर होगा।

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

+0

8192 'आदर्श' नहीं है, लेकिन आम तौर पर उपयोगी संख्या है। स्थिर-लंबाई वाले पैकेट में डेटा भेजने के लिए बेहतर नहीं है: जितना तेज़ हो सके इसे स्ट्रीम करना बेहतर है। भेजे गए डेटा का आकार पीयर पर 'recv()' द्वारा दिए गए मान के साथ जरूरी नहीं है। यह एक स्ट्रीमिंग प्रोटोकॉल है। – EJP

6

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

यह भी ध्यान रखें कि Receive को बार-बार कॉल करना अच्छा अभ्यास है जब तक कि आपने सत्यापित नहीं किया है कि आपने किसी दिए गए संदेश के लिए सभी डेटा पढ़ लिया है; भले ही एक संदेश आपके बफर आकार से कम है, फिर भी यह सभी को Receive कॉल द्वारा पुनर्प्राप्त नहीं किया जा सकता है।

4

जॉन स्कीट का जवाब दुर्भाग्य से तस्वीर के एक बड़े हिस्से को छोड़ देता है - भेजें बफर आकार, और bandwidth-delay product जिस पाइप को आप लिख रहे हैं।

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

एक कनेक्शन पर विचार करें जिसमें 1 गिगाबिट की गति है, और औसतन 10 मिलीसेकंड की एक तरफा विलंबता है। राउंड-ट्रिप-टाइम (उर्फ, उस समय की मात्रा जो आपके सॉकेट के बीच एक पैकेट भेजती है और वह उस पैकेट के लिए एक प्राप्त करती है और इस प्रकार अधिक डेटा भेजने के लिए जानता है) आमतौर पर विलंबता से दोगुनी होती है।

तो यदि आपके पास 1 गिगाबिट कनेक्शन है, और 20 मिलीसेकंड का आरटीटी है, तो उस पाइप में 1 गिगाबिट/सेकंड * 20 मिलीसेकंड == 2.5 मेगाबाइट डेटा उड़ान भरने पर पूरी तरह से उपयोग किया जा रहा है।

यदि आपका टीसीपी भेज बफर 2.5 मेगाबाइट से कम कुछ भी है, तो वह सॉकेट कभी भी पाइप का पूरी तरह से उपयोग नहीं करेगा - आपको कभी भी अपनी सॉकेट से प्रदर्शन का गीगाबिट/सेकंड नहीं मिलेगा।

यदि आपका एप्लिकेशन कई सॉकेट का उपयोग करता है, तो इस टीपीसी प्रेषण बफर का कुल आकार 2.5 एमबी होना चाहिए ताकि इस काल्पनिक 1 गीगाबिट/20 एमएस आरटीटी पाइप का पूरी तरह से उपयोग किया जा सके। उदाहरण के लिए, यदि आप 8192-बाइट बफर का उपयोग करते हैं, तो आपको उस पाइप को भरने के लिए 306 एक साथ टीसीपी सॉकेट की आवश्यकता होती है।