2011-03-20 6 views
6

मैंने कम से कम 10 बार प्रलेखन पढ़ा है और कुछ 10 या तो कोड स्निपेट और पूर्ण प्रोग्राम भी पढ़े हैं जहां डेटा भेजने के लिए गैर-अवरुद्ध सॉकेट का उपयोग किया जाता है। समस्या यह है कि कुछ ट्यूटोरियल या तो शुरुआती (बीजेस एफआईआई) के लिए हैं या उनकी धारणाओं में बहुत खराब हैं; और जो जटिल नहीं हैं वे विशेष कोड उदाहरण हैं जो यह नहीं बताते कि वे ऐसा क्यों करते हैं जो वे करते हैं। यहां तक ​​कि एसओ ज्ञान आधार भी मेरी राय में send व्यवहार के पूरे मैदान को पूरी तरह से कवर नहीं करता है। f.e पर विवरण क्या मैं के बाद कर रहा हूँ कर रहे हैं:क्या कोई मुझे गैर-अवरुद्ध सॉकेट के लिए 'प्रेषण' व्यवहार का अच्छा स्पष्टीकरण दे सकता है?

  • क्या वापस 0 से संकेत मिलता है कि वास्तव में के कोड होता है, और यह errno तो जाँच या एक बस आगे की जांच पड़ताल के बिना कनेक्शन त्यागने चाहिए लायक है?
  • एक नकारात्मक वापसी मान वारंट एक कनेक्शन बुरा चला बंद करने के लिए हो रही है, या यह केवल इसलिए जब तक errnoEWOULDBLOCK, EAGAIN या EINTR (... अन्य) है?
  • क्या वापसी मूल्य errno है जब वापसी मूल्य > 0 है? जाहिर है, मान "भेजा गया" डेटा उद्धृत करता है (उद्धरणों में क्योंकि यह वास्तव में एक लंबी प्रक्रिया है, सही है), लेकिन चूंकि सॉकेट गैर-अवरुद्ध है, इसका मतलब यह है कि कोई भी तुरंत एक और कॉल जारी कर सकता है, या errno पर निर्भर करता है , किसी को अगले प्रेषण अवसर (चयन/मतदान/एपोल का उपयोग करके) का इंतजार करना चाहिए?
  • असल में, क्या कोई पहले वापसी मूल्य की जांच करता है और केवल तभी errno मूल्य? या शायद send प्रत्येक कॉल पर errno सेट करता है, भले ही मूल्य वापसी? इससे त्रुटि कुछ आसान हो जाएगी ...
  • यदि कोई EINTR प्राप्त करता है, तो प्रोग्राम के लिए एक अच्छा, मजबूत व्यवहार क्या होगा? बस राज्य को रिकॉर्ड करें और अगले प्रेषण अवसर पर पुनः प्रयास करें, जैसे EWOULDBLOCK और EAGAIN?
  • क्या कोई दोनोंEWOULDBLOCKऔरEAGAIN पर जांच करता है? क्या हम दोनों एक ही मूल्य रखने पर भरोसा कर सकते हैं, या यह कार्यान्वयन पर निर्भर करता है?
  • क्या send धारा सॉकेट के लिए EMSGSIZE लौटाता है? यदि ऐसा नहीं होता है, तो कोई बफर आकार बहुत बड़ा नहीं है, है ना?
  • क्या मूल्य वापस ज्ञात त्रुटि कोड के बराबर हो सकता है?

यदि आप मजबूत गैर-अवरुद्ध प्रेषण कोड का उदाहरण प्रदान कर सकते हैं, तो इसकी पूरी सराहना की जाएगी।

उत्तर

9

सवाल यहाँ का एक बहुत:

  • क्या वापस करता है 0 के कोड वास्तव में संकेत मिलता है, और यह तो errno जाँच के लायक है या एक बस आगे की जांच पड़ताल के बिना कनेक्शन त्यागने चाहिए?

एक POSIX प्रणाली पर, भेज (2) वापस कभी नहीं कर सकते हैं 0 जब तक आप बनाने के लिए अपने विशिष्ट प्रणाली के लिए किए गए दस्तावेज़ों की 0. चेक लंबाई आर्ग से कॉल करने की यकीन है कि यह POSIX कल्पना

इस प्रकार है
  • क्या एक नकारात्मक रिटर्न वैल्यू वारंट प्राप्त हो रहा है जो कनेक्शन बंद कर रहा है, या यह केवल तब तक है जब तक कि त्रुटि गलत नहीं है, EAGAIN या EINTR (... अन्य)?

नहीं, एक -1 वापसी मान (केवल संभावित नकारात्मक वापसी मान) बस का अर्थ है कि कोई डेटा नहीं भेजा गया था। आप errno जाँच करने के लिए क्यों देखने की जरूरत - सभी संभव errno मूल्य की एक पूरी सूची के लिए भेजने (2) आदमी पेज देख सकते हैं और वे

  • क्या मतलब है यह जब वापसी मान> है जाँच errno लायक है 0? जाहिर है, मान "भेजे गए" डेटा की मात्रा इंगित करता है (उद्धरणों में क्योंकि यह वास्तव में एक लंबी प्रक्रिया है, सही है), लेकिन चूंकि सॉकेट गैर-अवरुद्ध है, इसका मतलब यह है कि कोई भी तुरंत एक और कॉल जारी कर सकता है, या फिर फिर से इरनो पर निर्भर करता है , किसी को अगले प्रेषण अवसर (चयन/मतदान/एपोल का उपयोग करके) का इंतजार करना चाहिए?

तो भेज रिटर्न सफलता (> 0), तो errno में बदलाव नहीं होगा और शामिल होंगे जो कुछ भी यह पहले था (जो शायद कुछ पहले सिस्टम कॉल से एक त्रुटि है)।

  • असल में, एक वापसी मान पहले और उसके बाद ही errno मान की जाँच करता है? या हो सकता है कि प्रत्येक कॉल पर इरनो सेट भेजें, भले ही मूल्य वापसी करें? यही कारण है कि त्रुटि कुछ हद तक आसान जाँच बनाना होगा ...

चेक वापसी मान पहले और उसके बाद errno अगर वापसी मान -1 है। क्या तुम सच में करना चाहते हैं, तो आप कॉल करने से पहले 0 errno सेट कर सकते हैं और फिर बाद में यह जाँच

  • एक हो जाता है EINTR, जो एक अच्छी, मजबूत एक कार्यक्रम के लिए व्यवहार हो सकता है? बस राज्य को रिकॉर्ड करें और अगले प्रेषण अवसर पर पुनः प्रयास करें, जैसे EWOULDBLOCK और EAGAIN के साथ?

खैर, सबसे सरल प्रणाली निरिक्षण जिस स्थिति में आप एक EINTR कभी नहीं मिलेगा में रुकावट निष्क्रिय करने के लिए है। इसे EWOULDBLOCK/EAGAIN के समान व्यवहार करना भी अच्छा है।

  • दोनों EWOULDBLOCK और EAGAIN के लिए एक चेक करता है? क्या हम दोनों एक ही मूल्य रखने पर भरोसा कर सकते हैं, या यह कार्यान्वयन पर निर्भर करता है?

कार्यान्वयन पर निर्भर करता है, हालांकि आम तौर पर वे समान होते हैं। कभी-कभी SysV बनाम बीएसडी अनुकरण मोड के साथ अलौकिकता है कि उन्हें अलग कर सकता है और या तो हो सकता है

  • है धारा सॉकेट के लिए बदले EMSGSIZE भेज रहा है? यदि ऐसा नहीं होता है, तो कोई बफर आकार बहुत बड़ा नहीं है, है ना?

स्ट्रीम सॉकेट परमाणु संदेशों की आवश्यकता नहीं है EMSGSIZE परमाणु संदेशों के लिए ही है, इसलिए कोई, धारा सॉकेट वापस नहीं लौट सकते EMSGSIZE

  • वापस लौटा सकते मूल्य खुद के बराबर हो तो ज्ञात त्रुटि कोड का?

एकमात्र त्रुटि कोड -1 है। सफलता बाइट्स की संख्या लिखी गई है, इसलिए यदि आप 32-बिट मशीन (या 64 बिट मशीन पर 2^64-1) पर 2^32-1 बाइट लिख सकते हैं, तो यह एक समस्या होगी, लेकिन आप नहीं कर सकते कई बाइट्स लिखें (और यदि आप कोशिश करते हैं तो आपको आम तौर पर एक ईविल या EFAULT मिल जाएगा)।

+1

भेजें (2) शून्य लौटाए जाने पर शून्य वापस कर सकते हैं 0। यूडीपी जैसे डाटाग्राम प्रोटोकॉल के लिए, इसका परिणाम शून्य-बाइट पैकेट भेजा जा सकता है। इसके अलावा, सफल लाइब्रेरी कॉल में इरनो को अपरिवर्तित होने की गारंटी नहीं है। – Anomie

+0

@Anomie: पहला भाग पर्याप्त है, लेकिन दूसरे के लिए, POSIX गारंटी देता है कि कुछ लाइब्रेरी कॉल त्रुटियों को संशोधित नहीं करेंगे अगर कोई त्रुटि नहीं है, और 'प्रेषण' उन कॉलों में से एक है। –

+0

आप इसे कहां देखते हैं? POSIX.1-2008 ऑनलाइन है [यहां] (http://pubs.opengroup.org/onlinepubs/9699919799/)। [Errno पर पृष्ठ] (http://pubs.opengroup.org/onlinepubs/9699919799/functions/errno.html) कहता है "फ़ंक्शन में सफल कॉल के बाद इरनो की सेटिंग अनिर्दिष्ट है जब तक कि उस फ़ंक्शन का विवरण निर्दिष्ट नहीं करता है errno संशोधित नहीं किया जाएगा ", और [भेजने के लिए पृष्ठ] (http://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html) ऐसी कोई बात नहीं प्रतीत होता है। – Anomie

3

मैं आपके सवालों का जवाब देने की कोशिश करूंगा।

  • send से 0 का वापसी मूल्य इंगित करता है कि 0 बाइट भेजे गए थे। एक त्रुटि 1 के रिटर्न वैल्यू द्वारा इंगित की जाती है। यदि आपने send को 0 की लंबाई के साथ बुलाया है, तो 0 की वापसी की उम्मीद की जानी चाहिए। जबकि गैर-अवरुद्ध सॉकेट को EAGAIN या EWOULDBLOCK की गलती के साथ -1 को वापस करना चाहिए, अगर यह ब्लॉक हो जाएगा, तो कुछ कार्यान्वयन के बजाय 0 बाइट्स लौटाए जाने पर मुझे अत्यधिक आश्चर्य नहीं होगा।
  • EWOULDBLOCK, EAGAIN, और EINTR त्रुटियां हैं जिन पर आपको पुनः प्रयास करना चाहिए, उनमें से किसी एक को प्राप्त करते समय कनेक्शन बंद न करें। अन्य त्रुटियां ऐसी समस्या का संकेत देती हैं जो शायद निकट में होनी चाहिए।
  • नहीं, सफल लाइब्रेरी कॉल के बाद इरनो की जांच न करें (जब तक कि दस्तावेज़ीकरण विशेष रूप से कहता है कि आप इसे किसी कारण से नहीं कर सकते हैं; मुझे ऐसा करने वाले किसी भी ऑफहैंड से अवगत नहीं है)। ध्यान दें कि सफल लाइब्रेरी कॉल में इरनो अपरिवर्तित नहीं रह सकता है, क्योंकि कॉल ने अन्य कॉल किए हैं जो त्रुटियों को वापस कर चुके हैं और उचित रूप से संभाले गए हैं (उदाहरण के लिए एक कॉल एक फ़ाइल को स्टेट करने का प्रयास कर सकता है, पूरी तरह से उम्मीद है कि यह अस्तित्व में नहीं है; errno तब भी ईनोन्ट होगा, भले ही कोई वास्तविक त्रुटि न हो)। यदि भेजना एक छोटा सा लिखता है, तो आप फिर से प्रयास कर सकते हैं (और संभवतः ईवॉल्डब्लॉक/ईजेन प्राप्त करें) या आप अगले select के लिए प्रतीक्षा कर सकते हैं।
  • हां, पहले वापसी मूल्य की जांच करें। errno कॉल सफल होने पर आपको कुछ भी उपयोगी नहीं बताता है।
  • ईआईएनटीआर पर, आप तुरंत पुनः प्रयास कर सकते हैं या अगली बार select लूप के माध्यम से प्रतीक्षा कर सकते हैं।
  • आपको दोनों ईगल और इडौल्डब्लॉक की जांच करनी होगी; मुझे लगता है कि यदि आप प्रदर्शन विशेष रूप से महत्वपूर्ण हैं (लेकिन याद रखें, प्रोफाइल फिर अनुकूलित करें) तो आप #if EAGAIN == EWOULDBLOCK कर सकते हैं।
  • यह सब अंतर्निहित प्रोटोकॉल पर निर्भर करेगा, लेकिन आम तौर पर मैं एक स्ट्रीमिंग प्रोटोकॉल पर परमाणु संदेश नहीं होने की अपेक्षा करता हूं (जब तक कि MSG_OOB का उपयोग न हो)। टीसीपी के लिए, कोई भी बफर आकार ठीक होना चाहिए।
  • यह निश्चित रूप से वापसी मूल्य के लिए किसी भी इंको स्थिरांक के बराबर है, लेकिन इसका मतलब कुछ भी नहीं है। उदाहरण के लिए, मेरे सिस्टम पर अगर 11 बाइट लिखे गए थे तो वापसी मूल्य EAGAIN के बराबर होगा।

एचटीएच।

2

EINTR और सिस्टम पर कॉल:

  • अगर आप glibc उपयोग कर रहे हैं, तो आप उस के बारे में चिंता करने की कम से कम सिस्टम कॉल के संदर्भ में जरूरत नहीं है। मुझे यह मिला है कि Glibc FAQ से, grep "क्यों सिग्नल सिस्टम सिस्टम को बाधित नहीं करता है?"

  • यदि आप LINUX का उपयोग कर रहे हैं, तो आपको शायद कनेक्ट() सिस्टम कॉल के अजीब अर्थशास्त्र के बारे में चिंता करने की ज़रूरत नहीं है, कि डेविड मैडो here पर rants। अन्यथा, एसिंक्रोनस कनेक्ट() कॉल के लिए usuall व्यवहार के अलावा अन्य के लिए तैयार रहें।

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