नेटवर्क हमेशा अप्रत्याशित है। टीसीपी इस यादृच्छिक व्यवहार को आपके लिए दूर कर देता है। टीसीपी एक अद्भुत चीज करता है: यह गारंटी देता है कि बाइट एक ही क्रम में पहुंचेंगे। परंतु! यह गारंटी देता है कि वे उसी तरह कटा हुआ पहुंचेंगे। आप बस नहीं मान सकते हैं कि कनेक्शन के एक छोर से प्रत्येक प्रेषण() वास्तव में बाइट्स की एक ही संख्या के साथ दूर अंत में एक recv() का परिणाम देगा।
जब आप socket.recv(x)
कहते हैं, तो आप कह रहे हैं कि 'सॉकेट से एक्स बाइट्स पढ़ने तक वापस न आएं'। इसे "अवरुद्ध I/O" कहा जाता है: जब तक आपका अनुरोध भर नहीं जाता है तब तक आप ब्लॉक (प्रतीक्षा) करेंगे। यदि आपके प्रोटोकॉल में प्रत्येक संदेश बिल्कुल 1024 बाइट था, तो socket.recv(1024)
पर कॉल करना बहुत अच्छा काम करेगा। लेकिन ऐसा लगता है कि यह सच नहीं है। यदि आपके संदेश बाइट्स की निश्चित संख्या हैं, तो बस उस नंबर को socket.recv()
पर पास करें और आप कर चुके हैं।
लेकिन यदि आपके संदेश अलग-अलग लंबाई के हो सकते हैं तो क्या होगा? पहली चीज़ जो आपको करने की ज़रूरत है: एक स्पष्ट संख्या के साथ socket.recv()
पर कॉल करना बंद करें। इस बदलना:
data = self.request.recv(1024)
इस के लिए
:
data = self.request.recv()
मतलब है recv()
हमेशा वापस आ जाएगी जब भी यह नया डेटा हो जाता है।
लेकिन अब आपको एक नई समस्या है: प्रेषक ने आपको एक पूरा संदेश कब भेजा है, तो आप कैसे जानते हैं? जवाब है: आप नहीं करते हैं। आपको संदेश की लंबाई को अपने प्रोटोकॉल का एक स्पष्ट हिस्सा बनाना होगा। यहां सबसे अच्छा तरीका है: प्रत्येक संदेश को लम्बाई के साथ उपसर्ग करें, या तो एक निश्चित आकार पूर्णांक के रूप में (socket.ntohs()
या socket.ntohl()
का उपयोग करके नेटवर्क बाइट ऑर्डर में परिवर्तित करें!) या कुछ डिलीमीटर (जैसे '123:') के बाद एक स्ट्रिंग के रूप में। यह दूसरा दृष्टिकोण अक्सर कम कुशल होता है, लेकिन पाइथन में यह आसान है।
एक बार जब आप इसे अपने प्रोटोकॉल में जोड़ देते हैं, तो आपको recv()
किसी भी समय डेटा की मनमानी मात्रा को वापस करने के लिए अपना कोड बदलना होगा। यह कैसे करें इसका एक उदाहरण यहां दिया गया है। मैंने इसे छद्म कोड के रूप में लिखने की कोशिश की, या टिप्पणियों के साथ आपको यह बताना है कि क्या करना है, लेकिन यह बहुत स्पष्ट नहीं था। तो मैंने इसे एक उपनिवेश द्वारा समाप्त अंकों की एक स्ट्रिंग के रूप में लम्बाई उपसर्ग का स्पष्ट रूप से उपयोग किया है।ये रहा:
length = None
buffer = ""
while True:
data += self.request.recv()
if not data:
break
buffer += data
while True:
if length is None:
if ':' not in buffer:
break
# remove the length bytes from the front of buffer
# leave any remaining bytes in the buffer!
length_str, ignored, buffer = buffer.partition(':')
length = int(length_str)
if len(buffer) < length:
break
# split off the full message from the remaining bytes
# leave any remaining bytes in the buffer!
message = buffer[:length]
buffer = buffer[length:]
length = None
# PROCESS MESSAGE HERE
स्रोत
2009-11-11 16:02:59
हंस एल नीचे टिप्पणी में सही है कि python request.recv() में एक अनिवार्य पैरा अगर bufize के रूप में वैध कॉल नहीं है। आदर्श रूप से यह उत्तर हटाया जाना चाहिए या संपादित किया जाना चाहिए। http://docs.python.org/library/socket.html – prashantsunkari
"इसे" अवरुद्ध I/O "कहा जाता है:" मुझे इस शब्द को ब्रेमेन डाउन में पसंद है .... – repzero