2010-02-19 10 views
6

recv() पुस्तकालय समारोह आदमी पेज की तुलना में कम है कि उल्लेख:मामला जब recv अवरुद्ध() रिटर्न का अनुरोध बाइट्स

यह रिटर्न बाइट की संख्या प्राप्त किया। यह सामान्य रूप से अनुरोध की गई राशि की प्राप्ति के इंतजार के बजाय, अनुरोधित राशि तक, कोई भी डेटा उपलब्ध कराता है।

हम recv() कॉल को अवरुद्ध और 100 बाइट्स के लिए अनुरोध किया उपयोग कर रहे हैं:

recv(sockDesc, buffer, size, 0); /* Where size is 100. */ 

और केवल 50 बाइट्स सर्वर तो यह recv() 100 बाइट्स तक अवरुद्ध है द्वारा भेज रहे हैं उपलब्ध हैं या इसे प्राप्त करने वापस आ जाएगी 50 बाइट्स

परिदृश्य हो सकता है कि:

sendign केवल 50 बाइट्स

  • बुरा प्रोटोकॉल डिजाइन जहां सर्वर केवल 50 बाइट्स भेज रहा है के बाद

    • सर्वर क्रैश हो जाता है, जबकि ग्राहक 100 की उम्मीद है और सर्वर भी इंतज़ार कर रहा है ग्राहक की जबाब

    मैं ली पर दिलचस्पी है (यानी सॉकेट घनिष्ठ संबंध सर्वर जिसमें recv वापस आ जाएगी द्वारा शुरू नहीं किया गया है) नक्स/सोलारिस मंच। मेरे पास इसे जांचने के लिए विकास पर्यावरण नहीं है।

  • उत्तर

    13

    recv वापस आ जाएगी आंतरिक बफ़र्स में डेटा लौटाने के लिए नहीं है जब। यदि आप 100 बाइट्स का अनुरोध करते हैं तो यह 100 बाइट्स तक इंतजार नहीं करेगा।

    यदि आप 100 बाइट "संदेश" भेज रहे हैं, तो याद रखें कि टीसीपी संदेश प्रदान नहीं करता है, यह सिर्फ एक स्ट्रीम है। यदि आप एप्लिकेशन संदेशों से निपट रहे हैं, तो आपको इसे एप्लिकेशन लेयर पर संभालना होगा क्योंकि टीसीपी ऐसा नहीं करेगा।

    ऐसी कई स्थितियां हैं जहां 100 बाइट्स की एक प्रेषण() कॉल दूसरे छोर पर पूरी तरह से पढ़ी नहीं जा सकती है, जबकि रिकव (..., 100) कॉल करते समय केवल एक रिकव कॉल के साथ; यहां सिर्फ एक कुछ उदाहरण है:

    • भेजने टीसीपी ढेर एक साथ 15 लिखने कॉल बंडल करने का फैसला किया, और MTU 1460 जो हुआ - पहुंचे डेटा के समय के आधार पर ग्राहकों को पहले 14 कारण हो सकता है 100 बाइट्स लाने के लिए कॉल और 15. 60 बाइट्स लाने के लिए कॉल - अगली बार बाइट अगली बार जब आप recv() को कॉल करेंगे।(लेकिन यदि आप 100 के बफर के साथ आरईवी को कॉल करते हैं, तो आपको पहले संदेश के पहले 40 बाइट और अगले संदेश के पहले 60 बाइट मिल सकते हैं)

    • प्रेषक बफर पूर्ण हैं, शायद पाठक धीमा है, या नेटवर्क भीड़ है। कुछ बिंदु पर, डेटा बफर खाली करने के दौरान हो सकता है और डेटा का अंतिम हिस्सा 100 का एक से अधिक हिस्सा नहीं था।

    • रिसीवर बफर पूर्ण हैं, जबकि आपका ऐप recv() वह डेटा, आखिरी खंड खींचता है केवल आंशिक है क्योंकि उस संदेश के पूरे 100 बाइट बफर फिट नहीं थे। आप से बढ़ाना के रूप में और गति नीचे जिस पर संदेश भेजे जाते हैं चीजों में अंतर हो सकता -

    इन परिदृश्यों में से कई नहीं बल्कि परीक्षण करने के लिए, विशेष रूप से एक लैन पर आप भीड़ या पैकेट क्षति के एक बहुत कुछ नहीं हो सकता है, जहां मुश्किल है/उत्पादन किया।

    वैसे भी। यदि आप एक सॉकेट से 100 बाइट्स पढ़ने के लिए चाहते हैं,

    int 
    readn(int f, void *av, int n) 
    { 
        char *a; 
        int m, t; 
    
        a = av; 
        t = 0; 
        while(t < n){ 
         m = read(f, a+t, n-t); 
         if(m <= 0){ 
          if(t == 0) 
           return m; 
          break; 
         } 
         t += m; 
        } 
        return t; 
    } 
    

    की तरह कुछ का उपयोग करें ...

    if(readn(mysocket,buffer,BUFFER_SZ) != BUFFER_SZ) { 
        //something really bad is going on. 
    
    } 
    
    +0

    विस्तृत स्पष्टीकरण के लिए धन्यवाद। बस पुष्टि कर रहा है कि यह * अवरुद्ध * recv() कॉल के लिए भी सही है या नहीं? (यानी recv() अनुरोध बाइट्स से कम के साथ वापसी) – Adil

    +0

    हां, यह एक अवरुद्ध आरईवी कॉल के लिए सच है। – nos

    2

    आप ठीक उद्धरण पढ़ते हैं, तो सबसे आम परिदृश्य है:

    • सॉकेट डेटा प्राप्त कर रहा है। उस 100 बाइट्स में कुछ समय लगेगा।
    • recv() कॉल किया गया है।
      • यदि बफर में 0 से अधिक बाइट्स हैं, तो recv() देता है जो उपलब्ध है और प्रतीक्षा नहीं करता है।
      • जबकि 0 बाइट्स उपलब्ध हैं, यह ब्लॉक और थ्रेडिंग सिस्टम की ग्रैन्युलरिटी निर्धारित करती है कि यह कितना समय है।
    +0

    धन्यवाद इसलिए इसका मतलब है कि अगर आरईवी() जारी किया गया है और डेटा उपलब्ध है (अनुरोध से कम), यह जो भी डेटा उपलब्ध है, उसके साथ वापस आ जाएगा। सही? – Adil

    7

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

    SO_RCVLOWAT

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

    +0

    SO_RCVLOWAT सॉकेट विकल्प है। अगर हमने कोई सॉकेट विकल्प सेट नहीं किया है और recv() को कोई ध्वज पास नहीं किया गया है, और recv() कॉल को अवरुद्ध कर दिया गया है, तो क्या यह सभी अनुरोधित बाइट्स की प्रतीक्षा करेगा? (सॉकेट क्लोज ऑपरेशन को भी initited नहीं किया गया है) – Adil

    +1

    स्थिति में आप अपनी पोस्ट में वर्णित स्थिति में यह 50 बाइट वापस आ जाएगा। यह ** ** पूर्ण 100 बाइट्स तक प्रतीक्षा नहीं करेगा जबतक कि आप 'MSG_WAITALL' ध्वज को 'recv' पर पास न करें। –

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