2009-05-04 11 views
14

चलो कहते हैं कि मैं एक सॉकेट से एक लाइन में पढ़ना चाहते हैं, मानक socket मॉड्यूल का उपयोग करते हैं:अजगर सॉकेट बफरिंग

def read_line(s): 
    ret = '' 

    while True: 
     c = s.recv(1) 

     if c == '\n' or c == '': 
      break 
     else: 
      ret += c 

    return ret 

वास्तव में क्या s.recv(1) में क्या होता है? क्या यह हर बार एक सिस्टम कॉल जारी करेगा? मुझे लगता है मैं कुछ बफरिंग, वैसे भी जोड़ना चाहिए लगता है:

हार्डवेयर और नेटवर्क वास्तविकताओं, 2 की एक अपेक्षाकृत छोटी शक्ति होना चाहिए bufsize का मूल्य, उदाहरण के लिए के साथ सबसे अच्छा मैच के लिए, 4096.

http://docs.python.org/library/socket.html#socket.socket.recv

लेकिन यह कुशल और थ्रेड-सुरक्षित बफरिंग लिखना आसान नहीं लगता है। अगर मैं file.readline() का उपयोग करता हूं तो क्या होगा?

# does this work well, is it efficiently buffered? 
s.makefile().readline() 
+0

"क्या यह हर बार सिस्टम कॉल जारी करेगा?" यह बात क्यों है? –

+6

क्योंकि सिस्टम कॉल धीमी हैं। डेटा का एक बड़ा हिस्सा (यदि उपलब्ध हो) लाने के लिए बेहतर है, तो इसे संसाधित करें। अब मुझे पता है कि पायथन विशेष रूप से तेज़ नहीं है, और शायद यह वास्तव में कोई फर्क नहीं पड़ता। लेकिन दस्तावेज कहता है कि वैसे भी बड़े हिस्सों द्वारा पढ़ना बेहतर होता है। –

+7

ध्यान दें कि '+ =' का उपयोग करके एक स्ट्रिंग का निर्माण करना कोई संख्या नहीं है क्योंकि यह संभावित रूप से वर्गबद्ध है, जबकि अंत में 'str.join' का उपयोग करके एक सूची बनाना हमेशा रैखिक होता है। –

उत्तर

18

recv() कॉल सी पुस्तकालय समारोह को फोन करके सीधे नियंत्रित किया जाता है।

यह सॉकेट के डेटा रखने के लिए प्रतीक्षा कर देगा। हकीकत में यह recv() सिस्टम कॉल ब्लॉक को बस देगा।

file.readline() एक कुशल buffered कार्यान्वयन है। यह थ्रेडसेफ नहीं है, क्योंकि ऐसा लगता है कि यह फ़ाइल को पढ़ने वाला एकमात्र है। , अंतर्निहित कोड का अनुरोध किया recv() केवल डेटा की मात्रा जाएगा

आप फ़ाइल वस्तु उपयोग कर रहे हैं (आगामी इनपुट बफरिंग द्वारा उदाहरण। के लिए), हर बार read() एक सकारात्मक तर्क के साथ कहा जाता है, जब तक कि यह पहले से ही बफ़र है।

यह बफ़र होगी यदि: जो एक पूर्ण बफर

  • पंक्ति के अंत बफर के अंत से पहले था पढ़ता

    • आप ReadLine() कहा जाता था,

    इस प्रकार बफर में डेटा छोड़ना। अन्यथा बफर आमतौर पर अधिक नहीं भरा जाता है।

    प्रश्न का लक्ष्य स्पष्ट नहीं है। यदि आपको यह देखने की आवश्यकता है कि डेटा पढ़ने से पहले उपलब्ध है या नहीं, तो आप select() कर सकते हैं या s.setblocking(False) के साथ सॉकेट को नॉनब्लॉकिंग मोड पर सेट कर सकते हैं। फिर, यदि कोई प्रतीक्षा डेटा नहीं है, तो अवरुद्ध करने के बजाए पढ़ना खाली हो जाएगा।

    क्या आप एकाधिक थ्रेड के साथ एक फ़ाइल या सॉकेट पढ़ रहे हैं? मैं एक ही कार्यकर्ता को सॉकेट पढ़ने और अन्य धागे से निपटने के लिए प्राप्त कतार में प्राप्त वस्तुओं को खिलाने पर रखता हूं।

    परामर्श Python Socket Module source और C Source that makes the system calls सलाह दें।

  • +0

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

    +0

    realines() वास्तविक समय नहीं है। इसलिए यह एसएमटीपी जैसी इंटरैक्टिव टीसीपी सेवाओं के लिए बेकार है, हालांकि रीडलाइन काम करने लगता है। – Jasen

    22

    आप प्रदर्शन के साथ संबंध और सॉकेट को नियंत्रित कर रहे हैं पूरी तरह से (आप उदाहरण के लिए एक पुस्तकालय में इसे पारित नहीं कर रहे हैं) तो को लागू करने अजगर में अपने स्वयं के बफरिंग कोशिश - अजगर string.find और string.split और इस तरह कर सकते हैं आश्चर्यजनक रूप से तेज़ हो।

    def linesplit(socket): 
        buffer = socket.recv(4096) 
        buffering = True 
        while buffering: 
         if "\n" in buffer: 
          (line, buffer) = buffer.split("\n", 1) 
          yield line + "\n" 
         else: 
          more = socket.recv(4096) 
          if not more: 
           buffering = False 
          else: 
           buffer += more 
        if buffer: 
         yield buffer 
    

    आप पेलोड लाइनों वह भी बहुत बड़ा नहीं हैं, कि बहुत तेजी से चलाना चाहिए, और कॉल अनावश्यक रूप से समारोह के भी कई परतों के माध्यम से कूद से बचने से मिलकर करने की उम्मीद है। मैं जानने में दिलचस्प होगा कि यह file.readline() या socket.recv (1) का उपयोग कैसे करता है।

    6
    def buffered_readlines(pull_next_chunk, buf_size=4096): 
        """ 
        pull_next_chunk is callable that should accept one positional argument max_len, 
        i.e. socket.recv or file().read and returns string of up to max_len long or 
        empty one when nothing left to read. 
    
        >>> for line in buffered_readlines(socket.recv, 16384): 
        ... print line 
        ... 
        >>> # the following code won't read whole file into memory 
        ... # before splitting it into lines like .readlines method 
        ... # of file does. Also it won't block until FIFO-file is closed 
        ... 
        >>> for line in buffered_readlines(open('huge_file').read): 
        ... # process it on per-line basis 
         ... 
        >>> 
        """ 
        chunks = [] 
        while True: 
        chunk = pull_next_chunk(buf_size) 
        if not chunk: 
         if chunks: 
         yield ''.join(chunks) 
         break 
        if not '\n' in chunk: 
         chunks.append(chunk) 
         continue 
        chunk = chunk.split('\n') 
        if chunks: 
         yield ''.join(chunks + [chunk[0]]) 
        else: 
         yield chunk[0] 
        for line in chunk[1:-1]: 
         yield line 
        if chunk[-1]: 
         chunks = [chunk[-1]] 
        else: 
         chunks = [] 
    
    संबंधित मुद्दे