2010-02-18 9 views
9

जब मैं सॉकेट पर BeginSend को कॉल करता हूं, तो मैं एक प्रतिनिधि को पास करता हूं जिसे डेटा भेजा जाने पर (एक अलग थ्रेड द्वारा) कहा जाएगा।एक ही सॉकेट पर कितने एसिंक सॉकेट अनुरोध चल रहे हैं?

क्या होगा यदि मैं किसी अन्य समय BeginSend को कॉल करता हूं, जबकि पहले अभी तक 'कॉलबैक' नहीं किया गया है?

डेटा भेजने के लिए सही व्यवहार क्या है? BeginSend करें, और कॉलबैक पर EndSend करें और एक और भेजें शुरू करें? या क्या वास्तव में एक ही समय में कई BeginSends काम करना बुद्धिमान है?

इस MSDN पर BeginSend पेज जो इस प्रश्न का उत्तर नहीं देता है: BeginSend msdn

उत्तर

16

ओके के रूप में। कहते हैं, कई लंबित BeginSend कॉल ठीक काम करेंगे। हालांकि आपको शायद कुछ चीजों को ध्यान में रखना होगा।

सबसे पहले अगर यह एक टीसीपी सॉकेट है तो यह अभी भी सहकर्मी से पीयर तक डेटा की एक धारा है।

दूसरा अगर आपके सभी BeginSend कॉल एक ही थ्रेड पर होते हैं तो परिणाम यह होगा कि सहकर्मी कॉल के क्रम में डेटा प्राप्त करता है। यदि आपकी BeginSend कॉल अलग-अलग धागे से होती हैं तो डेटा किसी भी क्रम में पहुंच सकता है क्योंकि प्रत्येक भेजने के बीच दौड़ की स्थिति होगी। यह आपके लिए महत्वपूर्ण हो सकता है या इससे कोई फर्क नहीं पड़ता (निर्भर करता है कि क्या आप अलग-अलग भेज रहे हैं, प्रत्येक प्रेषण के साथ संदेश पूरा करें या नहीं)।

तीसरा यदि आप टीसीपी का उपयोग कर रहे हैं और सॉकेट के दूसरे छोर पर कोड से तेज़ी से भेजना प्राप्त कर सकते हैं तो आप टीसीपी विंडो भर सकते हैं और टीसीपी स्टैक आपके डेटा स्ट्रीम पर प्रवाह नियंत्रण करने लगेंगे। यदि आप BeginSend कॉल जारी करना जारी रखते हैं तो आप ऐसी परिस्थिति में समाप्त हो सकते हैं जहां आपके कॉलबैक को आपके सर्वर कतार डेटा पर टीसीपी स्टैक के रूप में लंबे समय तक और लंबे समय तक कॉल करने के लिए कहा जाता है (आपको डेटा भेजने के बाद ही कॉलबैक मिल जाता है और टीसीपी विंडो आधारित प्रवाह नियंत्रण नए डेटा को तब तक रोका जा रहा है जब तक कि टीसीपी विंडो अब 'पूर्ण' न हो, यानी पीयर ने in flight के कुछ डेटा के लिए एसीके भेजा है)।

आप तब एक स्थिति में आ सकते हैं जिससे आप एक अनियंत्रित तरीके से भेजने की मशीन पर संसाधनों का उपयोग कर रहे हैं (आप BeginSend जारी करते हैं और यह नहीं पता कि यह कब पूरा होगा और प्रत्येक प्रेषण बफर को भेजा जा सकता है और संभावित रूप से स्मृति का उपयोग करता है non-paged pool विंसॉक कोड में नीचे ... Non-paged pool एक सिस्टम विस्तृत संसाधन है और प्री विस्टा ओएस पर काफी दुर्लभ है और कुछ बुरी तरह से व्यवहार किए गए ड्राइवर बॉक्स को नीली स्क्रीन कर सकते हैं यदि non-paged pool कम या थका हुआ है। आप और भी पेज लॉक कर सकते हैं मेमोरी में मेमोरी और लॉक मेमोरी पेजों की संख्या पर एक और सिस्टम की विस्तृत सीमा है।

इन मुद्दों के कारण आमतौर पर अपने प्रोटोकॉल स्तर प्रवाह को लागू करना सबसे अच्छा होता है नियंत्रण जो BeginSend कॉल की संख्या को सीमित करता है जिसे किसी भी समय लंबित किया जा सकता है (प्रोटोकॉल स्तर एसीके का उपयोग करके) या टीसीपी विंडो प्रवाह नियंत्रण के साथ काम करने के लिए और एक नया प्रेषण जारी करने के लिए लंबित प्रेषण के पूरा होने का उपयोग करें और आप कर सकते हैं कतार डेटा अपनी याद में भेजने के लिए और संसाधनों पर पूर्ण नियंत्रण है और यदि आप "बहुत अधिक" डेटा कतार करते हैं तो आप क्या करते हैं। इस बारे में अधिक विस्तार के लिए यहाँ अपने ब्लॉग पोस्ट देखें: http://www.serverframework.com/asynchronousevents/2011/06/tcp-flow-control-and-asynchronous-writes.html

इस का उत्तर देखें: टीसीपी विंडो प्रवाह नियंत्रण के बारे में अधिक जानकारी के लिए what happens when tcp/udp server is publishing faster than client is consuming? और क्या ओवरलैप आई/ओ के साथ होता है (C++ भूमि) जब आप इसे अनदेखा और इस मुद्दे को भी कई ओवरलैप भेजता है ...

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

+1

@ लेंस, यह एक अच्छा एक +1 है –

+0

@ लेंस: मेरे पास प्रोटोकॉल में बनाया गया खिड़की है जो मैं भेज रहा हूं (smpp) ताकि वे कभी भी तेजी से भेजने की बात न हों। आपके द्वारा उठाए गए आदेश बिंदु से बाहर एक मुद्दा होगा। – Toad

+0

@ लेन, उपरोक्त मेरी टिप्पणी में आपका नाम गलत वर्तनी, मेरी माफी :) –

4

मैं आधार पर मैं क्या read here, यह कई समवर्ती BeginSend होने की तरह लगता है क्या में सक्षम है।

अंश:

  1. आप एक ही समय में एक से अधिक BeginSends कतार कर सकते हैं। आपको लॉक
  2. की आवश्यकता नहीं है यदि आप कॉलबैक विधि नहीं बनाते हैं, तो आप कैसे जानते हैं कि भेजना सफल है? आप सफलता को अनदेखा करना चाहते हैं - आग की तरह और भूल जाएं - विधि, लेकिन फिर कम से कम को यह जानने की आवश्यकता है कि आपके प्रोग्राम को समाप्त करने के लिए सुरक्षित कब है।
  3. दूसरी चीज जो आप कर सकते हैं IAsyncResult का उपयोग करें जो आपको BeginSend से मिलता है। आप ऑपरेशन को पूरा करने के लिए प्रतीक्षा करने के लिए WaitHandle का उपयोग कर सकते हैं। लेकिन यह पहले स्थान पर Async का उपयोग करके के पूरे उद्देश्य को हरा देता है।
  4. मेरी सिफारिश कॉलबैक का उपयोग करना है, और सुनिश्चित करें कि कॉलबैक को कॉल किया गया है और आपके द्वारा भेजे गए बाइट्स की संख्या वास्तव में भेजी जाती है और अनुमोदित रूप से प्रेषण ऑपरेशन को समाप्त करती है।

अद्यतन:
एक साथ BeginSend की कोशिश की codes on MSDN और आंकड़ों के आधार पर बिना किसी अपवाद के लिए भेजा जाता है। हालांकि ध्यान रखें कि एक ही सॉकेट के लिए कनेक्शन पहले खोला जाना चाहिए। एक साथ BeginConnect काम नहीं करेगा।

+0

तो यह मल्टीप्लेक्स एकाधिक सॉकेट डेटा को एक सॉकेट पर स्ट्रीम करता है? क्या यह माइक्रोसॉफ्ट का एससीटीपी का जवाब है? –

+0

दिलचस्प। लेकिन क्या यह केवल एक लंबित BeginSend के साथ पैकेट प्रति पैकेट भेजने से तेज़ है? मैं यह पूछ रहा हूं क्योंकि मैं एक सर्वर बना रहा हूं जिसमें अच्छा प्रदर्शन होना चाहिए, और हो सकता है कि कम से कम एक्स लंबित होना चाहिए, सभ्य थ्रूपुट प्राप्त करना चाहता है। इस समय, मुझे – Toad

+0

रॉबर्ट नहीं पता होगा - नहीं, बिलकुल नहीं। यदि सॉकेट एक टीसीपी सॉकेट है तो आपके पास एक ही स्ट्रीम है। कई 'BeginSend' कॉल जारी करने से आप स्ट्रीम को असीमित रूप से कई लिखने की अनुमति देते हैं। –

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