Python 3.7 - Transports and Protocols

ट्रांसपोर्ट और प्रोटोकॉल




python

ट्रांसपोर्ट और प्रोटोकॉल

प्रस्तावना

ट्रांसपोर्ट और प्रोटोकॉल का उपयोग लो-लेवल इवेंट लूप APIs जैसे loop.create_connection() द्वारा किया जाता है। वे कॉलबैक-आधारित प्रोग्रामिंग शैली का उपयोग करते हैं और नेटवर्क या IPC प्रोटोकॉल (जैसे HTTP) के उच्च-प्रदर्शन कार्यान्वयन को सक्षम करते हैं।

अनिवार्य रूप से, ट्रांसपोर्ट और प्रोटोकॉल का उपयोग केवल पुस्तकालयों और रूपरेखाओं में किया जाना चाहिए और कभी भी उच्च-स्तरीय एसिंसीओ अनुप्रयोगों में नहीं होना चाहिए।

यह प्रलेखन पृष्ठ Transports और Protocols दोनों को कवर करता है।

परिचय

उच्चतम स्तर पर, परिवहन इस बात से संबंधित है कि बाइट्स को कैसे प्रसारित किया जाता है, जबकि प्रोटोकॉल निर्धारित करता है कि कौन से बाइट्स को संचारित करना है (और जब कुछ करना है)।

एक ही बात कहने का एक अलग तरीका: एक परिवहन सॉकेट (या समान I / O समापन बिंदु) के लिए एक अमूर्त है, जबकि एक प्रोटोकॉल परिवहन के दृष्टिकोण से एक आवेदन के लिए एक अमूर्त है।

फिर भी एक और दृश्य है परिवहन और प्रोटोकॉल इंटरफेस एक साथ नेटवर्क I / O और इंटरप्रोसेस I / O का उपयोग करने के लिए एक अमूर्त इंटरफ़ेस को परिभाषित करते हैं।

ट्रांसपोर्ट और प्रोटोकॉल ऑब्जेक्ट्स के बीच हमेशा 1: 1 संबंध होता है: प्रोटोकॉल डेटा भेजने के लिए ट्रांसपोर्ट विधियों को कॉल करता है, जबकि ट्रांसपोर्ट प्रोटोकॉल तरीकों को कॉल करता है जो इसे प्राप्त किया गया है।

कनेक्शन उन्मुख इवेंट लूप विधियों (जैसे loop.create_connection() ) के loop.create_connection() आमतौर पर एक ट्रांसपोर्ट ऑब्जेक्ट द्वारा दर्शाए गए एक स्वीकृत कनेक्शन के लिए एक प्रोटोकॉल ऑब्जेक्ट बनाने के लिए उपयोग किए जाने वाले एक प्रोटोकॉल_फैक्टरी तर्क को स्वीकार करते हैं। इस तरह के तरीके आमतौर पर (transport, protocol) की एक वापसी देते हैं।

अंतर्वस्तु

इस दस्तावेज़ पृष्ठ में निम्नलिखित अनुभाग हैं:

परिवहन

विभिन्न प्रकार के संचार माध्यमों को अमूर्त करने के लिए ट्रांसपोर्ट asyncio द्वारा प्रदान की जाने वाली कक्षाएं हैं।

परिवहन वस्तुओं को हमेशा एक रेफरी द्वारा asyncio event loop <asyncio-event-loop> किया जाता है: asyncio event loop <asyncio-event-loop>

asyncio औजार टीसीपी, यूडीपी, एसएसएल, और सबप्रोसेस पाइपों के लिए ट्रांसपोर्ट करता है। एक परिवहन पर उपलब्ध तरीके परिवहन के प्रकार पर निर्भर करते हैं।

परिवहन कक्षाएं थ्रेड सुरक्षित नहीं हैं।

परिवहन पदानुक्रम

class asyncio.BaseTransport

सभी ट्रांसपोर्ट के लिए बेस क्लास। ऐसे तरीके शामिल हैं जो सभी asyncio ट्रांसपोर्ट साझा करते हैं।

class asyncio.WriteTransport(BaseTransport)

केवल लेखन कनेक्शन के लिए एक आधार परिवहन।

WriteTransport वर्ग के उदाहरणों को loop.connect_write_pipe() ईवेंट लूप विधि से लौटाया जाता है और इसका उपयोग loop.subprocess_exec() जैसे उपप्रक्रम से संबंधित विधियों द्वारा भी किया जाता है।

class asyncio.ReadTransport(BaseTransport)

केवल पढ़ने के लिए कनेक्शन के लिए एक आधार परिवहन।

ReadTransport वर्ग के उदाहरणों को loop.connect_read_pipe() इवेंट लूप विधि से लौटाया जाता है और इसका उपयोग subprocess-related विधियों जैसे loop.subprocess_exec() द्वारा भी किया जाता है।

class asyncio.Transport(WriteTransport, ReadTransport)

एक द्विदिश परिवहन का प्रतिनिधित्व करने वाला इंटरफ़ेस, जैसे कि टीसीपी कनेक्शन।

उपयोगकर्ता सीधे एक परिवहन को तुरंत नहीं करता है; वे एक उपयोगिता समारोह कहते हैं, यह एक प्रोटोकॉल कारखाने और परिवहन और प्रोटोकॉल बनाने के लिए आवश्यक अन्य जानकारी को पारित करता है।

ट्रांसपोर्ट वर्ग के उदाहरण loop.create_connection() , loop.create_unix_connection() , loop.create_server() , loop.sendfile() , आदि जैसे इवेंट लूप विधियों से या उनके उपयोग से लौटाए जाते हैं।

class asyncio.DatagramTransport(BaseTransport)

डेटाग्राम (यूडीपी) कनेक्शन के लिए एक परिवहन।

DatagramTransport वर्ग के उदाहरण loop.create_datagram_endpoint() ईवेंट लूप विधि से लौटाए जाते हैं।

class asyncio.SubprocessTransport(BaseTransport)

एक अभिभावक और उसके बच्चे के ओएस प्रक्रिया के बीच संबंध का प्रतिनिधित्व करने के लिए एक अमूर्त।

loop.subprocess_shell() वर्ग के उदाहरण इवेंट लूप विधियों लूप। loop.subprocess_shell() और loop.subprocess_exec()

बेस ट्रांसपोर्ट

BaseTransport.close()

परिवहन बंद करें।

यदि ट्रांसपोर्ट में आउटगोइंग डेटा के लिए बफ़र है, तो बफ़र किए गए डेटा को एसिंक्रोनसली फ़्लश किया जाएगा। कोई और डेटा प्राप्त नहीं किया जाएगा। सभी बफ़र किए गए डेटा को फ़्लश करने के बाद, प्रोटोकॉल का protocol.connection_lost() विधि को इसके तर्क के रूप में None कहा जाएगा।

BaseTransport.is_closing()

यदि ट्रांसपोर्ट बंद हो रहा है या बंद है तो True लौटें।

BaseTransport.get_extra_info(name, default=None)

परिवहन या अंतर्निहित संसाधनों के बारे में जानकारी का उपयोग करें।

नाम एक स्ट्रिंग है जिसे प्राप्त करने के लिए परिवहन-विशिष्ट जानकारी के टुकड़े का प्रतिनिधित्व किया जाता है।

यदि जानकारी उपलब्ध नहीं है, या यदि परिवहन दिए गए तृतीय-पक्ष ईवेंट लूप कार्यान्वयन के साथ या वर्तमान प्लेटफ़ॉर्म पर क्वेरी करने का समर्थन नहीं करता है, तो डिफ़ॉल्ट मान वापसी का मान है।

उदाहरण के लिए, निम्न कोड परिवहन के अंतर्निहित सॉकेट ऑब्जेक्ट को प्राप्त करने का प्रयास करता है:

sock = transport.get_extra_info('socket')
if sock is not None:
    print(sock.getsockopt(...))

कुछ ट्रांसपोर्टों पर दी जा सकने वाली जानकारी की श्रेणियाँ:

  • सॉकेट:
    • 'peername' : वह रिमोट पता जिससे सॉकेट कनेक्ट किया गया है, सॉकेट का परिणाम है socket.socket.getpeername() (गलती पर None )
    • 'socket' : socket.socket उदाहरण
    • 'sockname' : सॉकेट का अपना पता, socket.socket.getsockname() का परिणाम
  • एसएसएल सॉकेट:
    • 'compression' : संपीड़न एल्गोरिथ्म एक स्ट्रिंग के रूप में इस्तेमाल किया जा रहा है, या None अगर कनेक्शन संकुचित नहीं है; ssl.SSLSocket.compression() का परिणाम
    • 'cipher' : एक तीन-मूल्य वाला टपल जिसमें इस्तेमाल किया जा रहा सिफर का नाम है, एसएसएल प्रोटोकॉल का संस्करण जो इसके उपयोग को परिभाषित करता है, और उपयोग किए जा रहे गुप्त बिट्स की संख्या; ssl.SSLSocket.cipher() का परिणाम
    • 'peercert' : सहकर्मी प्रमाणपत्र; ssl.SSLSocket.getpeercert() का परिणाम
    • 'sslcontext' : ssl.SSLContext उदाहरण
    • 'ssl_object' : ssl.SSLObject या ssl.SSLSocket उदाहरण
  • पाइप:
    • 'pipe' : पाइप ऑब्जेक्ट
  • उपप्रक्रिया:
BaseTransport.set_protocol(protocol)

एक नया प्रोटोकॉल सेट करें।

स्विचिंग प्रोटोकॉल केवल तभी किया जाना चाहिए जब दोनों प्रोटोकॉल स्विच का समर्थन करने के लिए प्रलेखित हों।

BaseTransport.get_protocol()

वर्तमान प्रोटोकॉल लौटाएं।

पढ़ें- केवल ट्रांसपोर्ट

ReadTransport.is_reading()

यदि ट्रांसपोर्ट नया डेटा प्राप्त कर रहा है तो True लौटें।

संस्करण 3.7 में नया।

ReadTransport.pause_reading()

परिवहन के प्राप्त अंत को रोकें। कोई भी डेटा प्रोटोकॉल के protocol.data_received() पास नहीं जाएगा resume_reading() विधि को फिर से शुरू होने तक resume_reading() कहा जाता है।

संस्करण 3.7 में परिवर्तित किया गया: यह विधि निष्प्राण है, अर्थात यह तब कहा जा सकता है जब परिवहन पहले से रुका हुआ या बंद हो।

ReadTransport.resume_reading()

प्राप्त अंत को फिर से शुरू करें। यदि पढ़ने के लिए कुछ डेटा उपलब्ध है, तो प्रोटोकॉल का protocol.data_received() विधि को एक बार फिर से कॉल किया जाएगा।

संस्करण 3.7 में परिवर्तित किया गया: यह विधि निष्प्राण है, अर्थात जब ट्रांसपोर्ट पहले से पढ़ रहा हो तो इसे कॉल किया जा सकता है।

केवल-लिखो परिवहन

WriteTransport.abort()

लंबित कार्यों के पूरा होने की प्रतीक्षा किए बिना, परिवहन को तुरंत बंद करें। बफ़र्ड डेटा खो जाएगा। कोई और डेटा प्राप्त नहीं किया जाएगा। प्रोटोकॉल का protocol.connection_lost() विधि को अंततः इसके तर्क के रूप में None कहा जाएगा।

WriteTransport.can_write_eof()

यदि ट्रांसपोर्ट write_eof() का समर्थन करता है तो True , यदि नहीं तो False

WriteTransport.get_write_buffer_size()

परिवहन द्वारा उपयोग किए जाने वाले आउटपुट बफर का वर्तमान आकार लौटाएं।

WriteTransport.get_write_buffer_limits()

प्रवाह नियंत्रण लिखने के लिए उच्च और निम्न वॉटरमार्क प्राप्त करें। एक टपल लौटाएं (low, high) जहां निम्न और उच्च बाइट्स की सकारात्मक संख्या है।

सीमा निर्धारित करने के लिए set_write_buffer_limits() का उपयोग करें।

संस्करण 3.4.2 में नया।

WriteTransport.set_write_buffer_limits(high=None, low=None)

लिखने के प्रवाह नियंत्रण के लिए उच्च और निम्न वॉटरमार्क सेट करें।

ये दो मान (बाइट्स की संख्या में मापा जाता है) जब प्रोटोकॉल के protocol.pause_writing() और protocol.resume_writing() विधियों को नियंत्रित करते हैं। यदि निर्दिष्ट किया गया है, तो निम्न वॉटरमार्क उच्च वॉटरमार्क से कम या उसके बराबर होना चाहिए। न तो उच्च और न ही निम्न नकारात्मक हो सकते हैं।

protocol.pause_writing() कहा जाता है जब बफर का आकार उच्च मूल्य से अधिक या उसके बराबर हो जाता है। यदि लेखन रोक दिया गया है, तो फिर से protocol.resume_writing() तब कहा जाता है जब बफर का आकार कम मूल्य के बराबर या उससे अधिक हो जाता है।

चूक कार्यान्वयन-विशिष्ट हैं। यदि केवल उच्च वॉटरमार्क दिया जाता है, तो कम वॉटरमार्क उच्च वॉटरमार्क के बराबर या उससे कम कार्यान्वयन-विशिष्ट मान को डिफॉल्ट करता है। शून्य से उच्च बल को निम्न के साथ शून्य पर सेट करना, और जब भी बफर गैर-रिक्त हो जाता है, तो protocol.pause_writing() कहा जाता है। बफर शून्य होने पर protocol.resume_writing() को कम करने का कारण बनता है। या तो सीमा के लिए शून्य का उपयोग आमतौर पर उप-इष्टतम है क्योंकि यह I / O करने के लिए अवसरों को कम करता है और समवर्ती रूप से गणना करता है।

लिमिट पाने के लिए get_write_buffer_limits() का उपयोग करें।

WriteTransport.write(data)

परिवहन के लिए कुछ डेटा बाइट्स लिखें।

यह विधि अवरुद्ध नहीं करती है; यह डेटा को बफ़र करता है और इसके लिए एसिंक्रोनस रूप से भेजने की व्यवस्था करता है।

WriteTransport.writelines(list_of_data)

परिवहन के लिए डेटा बाइट्स की एक सूची (या कोई पुनरावृत्ति) लिखें। यह कार्यात्मक रूप से चलने योग्य द्वारा उत्पादित प्रत्येक तत्व पर कॉलिंग write() बराबर है, लेकिन इसे अधिक कुशलता से लागू किया जा सकता है।

WriteTransport.write_eof()

सभी बफ़र किए गए डेटा को फ़्लश करने के बाद ट्रांसपोर्ट का राइट एंड बंद करें। डेटा अभी भी प्राप्त हो सकता है।

यह विधि NotImplementedError को बढ़ा NotImplementedError यदि परिवहन (जैसे SSL) आधे बंद कनेक्शनों का समर्थन नहीं करता है।

डेटाग्राम ट्रांसपोर्ट

DatagramTransport.sendto(data, addr=None)

Addr (एक ट्रांसपोर्ट-डिपेंडेंट टारगेट एड्रेस) द्वारा दिए गए रिमोट पीयर को डेटा बाइट्स भेजें। यदि Addr None , तो डेटा को परिवहन निर्माण पर दिए गए लक्ष्य पते पर भेजा जाता है।

यह विधि अवरुद्ध नहीं करती है; यह डेटा को बफ़र करता है और इसके लिए एसिंक्रोनस रूप से भेजने की व्यवस्था करता है।

DatagramTransport.abort()

लंबित कार्यों के पूरा होने की प्रतीक्षा किए बिना, परिवहन को तुरंत बंद करें। बफ़र्ड डेटा खो जाएगा। कोई और डेटा प्राप्त नहीं किया जाएगा। प्रोटोकॉल का protocol.connection_lost() विधि को अंततः इसके तर्क के रूप में None कहा जाएगा।

सबप्रोसेस ट्रांसपोर्ट

SubprocessTransport.get_pid()

पूर्णांक प्रक्रिया आईडी को पूर्णांक के रूप में लौटाएं।

SubprocessTransport.get_pipe_transport(fd)

पूर्णांक फ़ाइल डिस्क्रिप्टर fd के अनुरूप संचार पाइप के लिए परिवहन लौटें:

  • 0 : मानक इनपुट ( स्टडिन ) का पठनीय स्ट्रीमिंग ट्रांसपोर्ट, या None अगर stdin=PIPE के साथ stdin=PIPE नहीं बनाया गया था
  • 1 : मानक आउटपुट ( stdout ) का उपयुक्त स्ट्रीमिंग ट्रांसपोर्टेशन, या None अगर उपप्रकार को stdout=PIPE के साथ नहीं बनाया गया था
  • 2 : मानक त्रुटि ( stderr ) की उपयुक्त स्ट्रीमिंग ट्रांसपोर्टेशन, या अगर सबप्रोडर को stderr=PIPE के साथ नहीं बनाया गया था
  • अन्य एफडी : None
SubprocessTransport.get_returncode()

सबप्रोसेस रिटर्न कोड को एक पूर्णांक के रूप में लौटाएं या अगर यह नहीं लौटा है, तो यह subprocess.Popen.returncode समान है। subprocess.Popen.returncode विशेषता।

SubprocessTransport.kill()

उपप्रकार को मारें।

POSIX सिस्टम पर, फ़ंक्शन SIGKILL को उपप्रकार में भेजता है। विंडोज पर, यह विधि terminate() लिए एक उपनाम है।

subprocess.Popen.kill() भी देखें। subprocess.Popen.kill()

SubprocessTransport.send_signal(signal)

उपप्रकार को संकेत संख्या भेजें, जैसा कि subprocess.Popen.send_signal() में है। subprocess.Popen.send_signal()

SubprocessTransport.terminate()

उपप्रकार बंद करो।

POSIX सिस्टम पर, यह विधि उपप्रकार को SIGTERM भेजता है। विंडोज पर, विंडोज एपीआई फ़ंक्शन टर्मिनेटप्रोसेस () को सबप्रोसेस को रोकने के लिए कहा जाता है।

subprocess.Popen.terminate() भी देखें। subprocess.Popen.terminate()

SubprocessTransport.close()

मार kill() विधि kill() कॉल करके उपप्रकार को kill()

यदि उपप्रकार अभी तक वापस नहीं आया है, और स्टडिन , स्टडआउट और स्टेडर पाइप के करीब परिवहन।

प्रोटोकॉल

asyncio अमूर्त आधार वर्गों का एक सेट प्रदान करता है जिसका उपयोग नेटवर्क प्रोटोकॉल को लागू करने के लिए किया जाना चाहिए। उन वर्गों को transports साथ एक साथ उपयोग किया जाना है।

अमूर्त आधार प्रोटोकॉल कक्षाओं के उपवर्ग कुछ या सभी विधियों को लागू कर सकते हैं। ये सभी तरीके कॉलबैक हैं: उन्हें कुछ घटनाओं पर ट्रांसपोर्ट द्वारा बुलाया जाता है, उदाहरण के लिए जब कुछ डेटा प्राप्त होता है। एक आधार प्रोटोकॉल विधि को संबंधित परिवहन द्वारा बुलाया जाना चाहिए।

बेस प्रोटोकॉल

class asyncio.BaseProtocol

बेस प्रोटोकॉल उन विधियों के साथ जो सभी प्रोटोकॉल साझा करते हैं।

class asyncio.Protocol(BaseProtocol)

स्ट्रीमिंग प्रोटोकॉल (टीसीपी, यूनिक्स सॉकेट्स आदि) को लागू करने के लिए आधार वर्ग।

class asyncio.BufferedProtocol(BaseProtocol)

प्राप्त बफर के मैनुअल नियंत्रण के साथ स्ट्रीमिंग प्रोटोकॉल को लागू करने के लिए एक आधार वर्ग।

class asyncio.DatagramProtocol(BaseProtocol)

डेटाग्राम (यूडीपी) प्रोटोकॉल को लागू करने के लिए आधार वर्ग।

class asyncio.SubprocessProtocol(BaseProtocol)

बाल प्रक्रियाओं (यूनिडायरेक्शनल पाइप) के साथ संचार करने वाले प्रोटोकॉल को लागू करने के लिए आधार वर्ग।

बेस प्रोटोकॉल

सभी asyncio प्रोटोकॉल बेस प्रोटोकॉल कॉलबैक को लागू कर सकते हैं।

कनेक्शन कॉलबैक

कनेक्शन कॉलबैक को सभी प्रोटोकॉल पर बुलाया जाता है, एक सफल कनेक्शन के अनुसार। अन्य सभी प्रोटोकॉल कॉलबैक को केवल उन दो तरीकों के बीच कहा जा सकता है।

BaseProtocol.connection_made(transport)

कनेक्शन करने पर कॉल किया जाता है।

परिवहन तर्क कनेक्शन का प्रतिनिधित्व करने वाला परिवहन है। प्रोटोकॉल इसके परिवहन के संदर्भ को संग्रहीत करने के लिए जिम्मेदार है।

BaseProtocol.connection_lost(exc)

कनेक्शन खो जाने या बंद होने पर कॉल किया जाता है।

तर्क या तो अपवाद वस्तु है या None । उत्तरार्द्ध का मतलब है कि एक नियमित ईओएफ प्राप्त होता है, या कनेक्शन को इस कनेक्शन से हटा दिया गया था या बंद कर दिया गया था।

प्रवाह नियंत्रण कॉलबैक

प्रवाह नियंत्रण कॉलबैक को प्रोटोकॉल द्वारा किए गए लेखन को रोकने या फिर से शुरू करने के लिए ट्रांसपोर्ट द्वारा बुलाया जा सकता है।

अधिक विवरण के लिए set_write_buffer_limits() विधि का प्रलेखन देखें।

BaseProtocol.pause_writing()

उच्च वॉटरमार्क पर परिवहन का बफर जाने पर कॉल किया जाता है।

BaseProtocol.resume_writing()

कम वॉटरमार्क के नीचे परिवहन के बफर नालियों को कॉल किया जाता है।

यदि बफ़र आकार उच्च वॉटरमार्क के बराबर होता है, तो protocol.pause_writing() नहीं कहा जाता है: बफ़र आकार को सख्ती से समाप्त हो जाना चाहिए।

इसके विपरीत, फिर से protocol.resume_writing() को तब कहा जाता है जब बफर का आकार कम वॉटरमार्क के बराबर या कम होता है। यह सुनिश्चित करने के लिए ये अंतिम स्थितियाँ महत्वपूर्ण हैं कि जब जीरो मार्क हो तो चीजें अपेक्षित हों।

स्ट्रीमिंग प्रोटोकॉल

ईवेंट विधियाँ, जैसे loop.create_server() , loop.create_unix_server() , loop.create_connection() , loop.create_unix_connection() , loop.connect_accepted_socket() , loop.connect_read_pipe() , और loop.connect_write_pipe() - loop.connect_write_pipe() रिटर्न स्ट्रीमिंग प्रोटोकॉल।

Protocol.data_received(data)

कुछ डेटा प्राप्त होने पर कॉल किया जाता है। डेटा एक गैर-खाली बाइट्स ऑब्जेक्ट है जिसमें आने वाला डेटा है।

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

कनेक्शन को खोलने के दौरान विधि को एक मनमानी संख्या कहा जा सकता है।

हालाँकि, protocol.eof_received() को सबसे अधिक बार कहा जाता है। एक बार eof_received() कहा जाता है, data_received() को अब नहीं कहा जाता है।

Protocol.eof_received()

जब दूसरे छोर से संकेत मिलता है तो इसे कोई और डेटा नहीं भेजा जाएगा (उदाहरण के लिए write_eof() कॉल करके, यदि दूसरा छोर भी एसिंसीओ का उपयोग करता है)।

यह विधि गलत मान दे सकती है ( None सहित), जिस स्थिति में परिवहन स्वयं बंद हो जाएगा। इसके विपरीत, यदि यह विधि सही मान देती है, तो उपयोग किया गया प्रोटोकॉल निर्धारित करता है कि परिवहन बंद करना है या नहीं। चूंकि डिफ़ॉल्ट कार्यान्वयन None देता है, यह अंतर्निहित रूप से कनेक्शन बंद कर देता है।

SSL सहित कुछ परिवहन, आधे-बंद कनेक्शनों का समर्थन नहीं करते हैं, ऐसे में इस विधि से सही लौटने पर कनेक्शन बंद हो जाएगा।

राज्य मशीन:

start -> connection_made
    [-> data_received]*
    [-> eof_received]?
-> connection_lost -> end

बफरिंग स्ट्रीमिंग प्रोटोकॉल

संस्करण 3.7 में नया: महत्वपूर्ण: यह अनंतिम आधार पर पायथन 3.7 में asyncio में जोड़ा गया है! यह एक प्रायोगिक एपीआई के रूप में है जिसे अजगर 3.8 में पूरी तरह से बदला या हटाया जा सकता है।

बफरिंग प्रोटोकॉल किसी भी इवेंट लूप विधि के साथ उपयोग किया जा सकता है जो स्ट्रीमिंग प्रोटोकॉल का समर्थन करता है।

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

निम्नलिखित कॉलबैक BufferedProtocol इंस्टेंस पर कहे जाते हैं:

BufferedProtocol.get_buffer(sizehint)

एक नया प्राप्त बफर आवंटित करने के लिए कहा जाता है।

sizehint लौटे बफर के लिए अनुशंसित न्यूनतम आकार है। यह आकार- प्रकार के संकेत से छोटे या बड़े बफ़र्स को वापस करने के लिए स्वीकार्य है। जब -1 पर सेट किया जाता है, तो बफर आकार मनमाना हो सकता है। यह एक शून्य आकार के साथ एक बफर वापस करने के लिए एक त्रुटि है।

get_buffer() बफर प्रोटोकॉल को लागू करने वाली एक वस्तु को वापस करना चाहिए।

BufferedProtocol.buffer_updated(nbytes)

जब प्राप्त डेटा के साथ बफर को अपडेट किया गया था तब कॉल किया गया था।

nbytes बाइट्स की कुल संख्या है जो बफर को लिखा गया था।

BufferedProtocol.eof_received()

protocol.eof_received() . protocol.eof_received() विधि के प्रलेखन देखें।

get_buffer() को एक कनेक्शन के दौरान कई बार मनमानी संख्या कहा जा सकता है। हालाँकि, protocol.eof_received() . get_buffer() को सबसे अधिक बार कॉल किया जाता है और, अगर कॉल किया जाता है, तो get_buffer() और buffer_updated() इसके बाद कॉल नहीं किया जाएगा।

राज्य मशीन:

start -> connection_made
    [-> get_buffer
        [-> buffer_updated]?
    ]*
    [-> eof_received]?
-> connection_lost -> end

डेटाग्राम प्रोटोकॉल

डाटाग्राम प्रोटोकॉल इंस्टेंसेस का निर्माण प्रोटोकॉल फैक्ट्रियों द्वारा पारित किया जाना चाहिए। loop.create_datagram_endpoint() विधि से।

DatagramProtocol.datagram_received(data, addr)

डेटाग्राम प्राप्त होने पर कॉल किया जाता है। डेटा एक बाइट्स ऑब्जेक्ट है जिसमें आने वाला डेटा है। अतिरिक्त डेटा भेजने वाले का पता है; सटीक प्रारूप परिवहन पर निर्भर करता है।

DatagramProtocol.error_received(exc)

पिछले भेजे या संचालन प्राप्त करने पर OSError उठाता है। exc OSError उदाहरण है।

इस पद्धति को दुर्लभ परिस्थितियों में कहा जाता है, जब परिवहन (उदाहरण के लिए यूडीपी) यह पता लगाता है कि एक डेटाग्राम को उसके प्राप्तकर्ता तक नहीं पहुंचाया जा सकता है। हालांकि कई परिस्थितियों में, undeliverable डेटाग्रास चुपचाप गिरा दिया जाएगा।

ध्यान दें

BSD सिस्टम (macOS, FreeBSD, आदि) पर प्रवाह नियंत्रण डेटाग्राम प्रोटोकॉल के लिए समर्थित नहीं है, क्योंकि बहुत सारे पैकेट लिखने के कारण भेजने में विफलताओं का पता लगाने का कोई विश्वसनीय तरीका नहीं है।

सॉकेट हमेशा 'तैयार' दिखाई देता है और अतिरिक्त पैकेट गिरा दिए जाते हैं। एक OSError जिसके पास OSError से OSError के errno सेट है errno.ENOBUFS को उठाया या नहीं उठाया जा सकता है; यदि इसे उठाया जाता है, तो इसे DatagramProtocol.error_received() को सूचित किया जाएगा, लेकिन अन्यथा अनदेखा किया जाएगा।

सबप्रोसेस प्रोटोकॉल

डाटाग्राम प्रोटोकॉल इंस्टेंसेस का निर्माण प्रोटोकॉल फैक्ट्रियों द्वारा loop.subprocess_exec() और loop.subprocess_shell() तरीकों से किया जाना चाहिए।

SubprocessProtocol.pipe_data_received(fd, data)

जब बच्चे की प्रक्रिया अपने स्टडआउट या स्टेडर पाइप में डेटा लिखती है, तब कॉल किया जाता है।

fd पाइप का पूर्णांक फ़ाइल डिस्क्रिप्टर है।

डेटा एक गैर-खाली बाइट्स ऑब्जेक्ट है जिसमें प्राप्त डेटा है।

SubprocessProtocol.pipe_connection_lost(fd, exc)

बच्चे की प्रक्रिया के साथ संचार करने वाले पाइपों में से एक बंद होने पर कॉल किया जाता है।

fd पूर्णांक फ़ाइल डिस्क्रिप्टर है जिसे बंद कर दिया गया था।

SubprocessProtocol.process_exited()

जब बच्चा प्रक्रिया से बाहर निकल गया है तो कॉल किया गया।

उदाहरण

टीसीपी इको सर्वर

loop.create_server() विधि का उपयोग करके एक टीसीपी इको सर्वर बनाएं, प्राप्त डेटा वापस भेजें, और कनेक्शन बंद करें:

import asyncio


class EchoServerClientProtocol(asyncio.Protocol):
    def connection_made(self, transport):
        peername = transport.get_extra_info('peername')
        print('Connection from {}'.format(peername))
        self.transport = transport

    def data_received(self, data):
        message = data.decode()
        print('Data received: {!r}'.format(message))

        print('Send: {!r}'.format(message))
        self.transport.write(data)

        print('Close the client socket')
        self.transport.close()


async def main():
    # Get a reference to the event loop as we plan to use
    # low-level APIs.
    loop = asyncio.get_running_loop()

    server = await loop.create_server(
        lambda: EchoServerClientProtocol(),
        '127.0.0.1', 8888)

    async with server:
        await server.serve_forever()


asyncio.run(main())

यह भी देखें

स्ट्रीम उदाहरण का उपयोग करते हुए टीसीपी इको सर्वर उच्च-स्तरीय asyncio.start_server() फ़ंक्शन का उपयोग करता है।

टीसीपी इको क्लाइंट

एक TCP गूंज क्लाइंट का उपयोग कर loop.create_connection() विधि, डेटा भेजता है, और कनेक्शन बंद होने तक इंतजार करता है:

import asyncio


class EchoClientProtocol(asyncio.Protocol):
    def __init__(self, message, on_con_lost, loop):
        self.message = message
        self.loop = loop
        self.on_con_lost = on_con_lost

    def connection_made(self, transport):
        transport.write(self.message.encode())
        print('Data sent: {!r}'.format(self.message))

    def data_received(self, data):
        print('Data received: {!r}'.format(data.decode()))

    def connection_lost(self, exc):
        print('The server closed the connection')
        self.on_con_lost.set_result(True)


async def main():
    # Get a reference to the event loop as we plan to use
    # low-level APIs.
    loop = asyncio.get_running_loop()

    on_con_lost = loop.create_future()
    message = 'Hello World!'

    transport, protocol = await loop.create_connection(
        lambda: EchoClientProtocol(message, on_con_lost, loop),
        '127.0.0.1', 8888)

    # Wait until the protocol signals that the connection
    # is lost and close the transport.
    try:
        await on_con_lost
    finally:
        transport.close()


asyncio.run(main())

यह भी देखें

स्ट्रीम उदाहरण का उपयोग करते हुए टीसीपी इको क्लाइंट उच्च-स्तरीय asyncio.open_connection() फ़ंक्शन का उपयोग करता है।

यूडीपी इको सर्वर

एक UDP इको सर्वर, loop.create_datagram_endpoint() विधि का उपयोग करके, प्राप्त डेटा को वापस भेजता है:

import asyncio


class EchoServerProtocol:
    def connection_made(self, transport):
        self.transport = transport

    def datagram_received(self, data, addr):
        message = data.decode()
        print('Received %r from %s' % (message, addr))
        print('Send %r to %s' % (message, addr))
        self.transport.sendto(data, addr)


async def main():
    print("Starting UDP server")

    # Get a reference to the event loop as we plan to use
    # low-level APIs.
    loop = asyncio.get_running_loop()

    # One protocol instance will be created to serve all
    # client requests.
    transport, protocol = await loop.create_datagram_endpoint(
        lambda: EchoServerProtocol(),
        local_addr=('127.0.0.1', 9999))

    try:
        await asyncio.sleep(3600)  # Serve for 1 hour.
    finally:
        transport.close()


asyncio.run(main())

यूडीपी इको क्लाइंट

UDP इको क्लाइंट, loop.create_datagram_endpoint() विधि का उपयोग करते हुए, डेटा भेजता है और जब यह जवाब मिलता है तो परिवहन बंद कर देता है:

import asyncio


class EchoClientProtocol:
    def __init__(self, message, loop):
        self.message = message
        self.loop = loop
        self.transport = None
        self.on_con_lost = loop.create_future()

    def connection_made(self, transport):
        self.transport = transport
        print('Send:', self.message)
        self.transport.sendto(self.message.encode())

    def datagram_received(self, data, addr):
        print("Received:", data.decode())

        print("Close the socket")
        self.transport.close()

    def error_received(self, exc):
        print('Error received:', exc)

    def connection_lost(self, exc):
        print("Connection closed")
        self.on_con_lost.set_result(True)


async def main():
    # Get a reference to the event loop as we plan to use
    # low-level APIs.
    loop = asyncio.get_running_loop()

    message = "Hello World!"
    transport, protocol = await loop.create_datagram_endpoint(
        lambda: EchoClientProtocol(message, loop),
        remote_addr=('127.0.0.1', 9999))

    try:
        await protocol.on_con_lost
    finally:
        transport.close()


asyncio.run(main())

मौजूदा सॉकेट कनेक्ट करना

प्रतीक्षा करें जब तक एक सॉकेट loop.create_connection() का उपयोग करके डेटा प्राप्त नहीं करता है। प्रोटोकॉल के साथ loop.create_connection() विधि:

import asyncio
import socket


class MyProtocol(asyncio.Protocol):

    def __init__(self, loop):
        self.transport = None
        self.on_con_lost = loop.create_future()

    def connection_made(self, transport):
        self.transport = transport

    def data_received(self, data):
        print("Received:", data.decode())

        # We are done: close the transport;
        # connection_lost() will be called automatically.
        self.transport.close()

    def connection_lost(self, exc):
        # The socket has been closed
        self.on_con_lost.set_result(True)


async def main():
    # Get a reference to the event loop as we plan to use
    # low-level APIs.
    loop = asyncio.get_running_loop()

    # Create a pair of connected sockets
    rsock, wsock = socket.socketpair()

    # Register the socket to wait for data.
    transport, protocol = await loop.create_connection(
        lambda: MyProtocol(loop), sock=rsock)

    # Simulate the reception of data from the network.
    loop.call_soon(wsock.send, 'abc'.encode())

    try:
        await protocol.on_con_lost
    finally:
        transport.close()
        wsock.close()

asyncio.run(main())

यह भी देखें

पढ़ी गई घटनाओं के उदाहरण के लिए फ़ाइल डिस्क्रिप्टर देखने के लिए , एफडी दर्ज करने के लिए निम्न-स्तरीय loop.add_reader() विधि का उपयोग किया जाता है।

धाराओं उदाहरण का उपयोग करके डेटा की प्रतीक्षा करने के लिए एक पंजीकृत सॉकेट रजिस्टर एक coroutine में asyncio.open_connection() फ़ंक्शन द्वारा बनाई गई उच्च-स्तरीय धाराओं का उपयोग करता है।

loop.subprocess_exec () और SubprocessProtocol

सबप्रोसेस प्रोटोकॉल का एक उदाहरण एक सबप्रोसेस का आउटपुट पाने के लिए और सबप्रोसेस निकास के लिए प्रतीक्षा करने के लिए उपयोग किया जाता है।

loop.subprocess_exec() को th loop.subprocess_exec() विधि द्वारा बनाया जाता है:

import asyncio
import sys

class DateProtocol(asyncio.SubprocessProtocol):
    def __init__(self, exit_future):
        self.exit_future = exit_future
        self.output = bytearray()

    def pipe_data_received(self, fd, data):
        self.output.extend(data)

    def process_exited(self):
        self.exit_future.set_result(True)

async def get_date():
    # Get a reference to the event loop as we plan to use
    # low-level APIs.
    loop = asyncio.get_running_loop()

    code = 'import datetime; print(datetime.datetime.now())'
    exit_future = asyncio.Future(loop=loop)

    # Create the subprocess controlled by DateProtocol;
    # redirect the standard output into a pipe.
    transport, protocol = await loop.subprocess_exec(
        lambda: DateProtocol(exit_future),
        sys.executable, '-c', code,
        stdin=None, stderr=None)

    # Wait for the subprocess exit using the process_exited()
    # method of the protocol.
    await exit_future

    # Close the stdout pipe.
    transport.close()

    # Read the output which was collected by the
    # pipe_data_received() method of the protocol.
    data = bytes(protocol.output)
    return data.decode('ascii').rstrip()

if sys.platform == "win32":
    asyncio.set_event_loop_policy(
        asyncio.WindowsProactorEventLoopPolicy())

date = asyncio.run(get_date())
print(f"Current date: {date}")

उच्च-स्तरीय API का उपयोग करके लिखा गया उदाहरण भी देखें।