2011-08-04 26 views
12

पायथन फ़ाइल ऑब्जेक्ट्स में एक रीड विधि होती है जो एक वैकल्पिक आकार तर्क लेती है, जो मूल रूप से अधिकतम बाइट्स लौटने के लिए होती है। उदाहरण के लिए:क्या मुझे एक सॉकेट.मेकफाइल मिल सकता है जो एक नियमित रूप से पढ़ने के लिए एक ही पढ़ा अर्थशास्त्र है?

fname = "message.txt" 
open(fname, "w").write("Hello World!") 
print open(fname).read() # prints the entire file contents 
print open(fname).read(5) # print "Hello" 
print open(fname).read(99) # prints "Hello World!" 

तो भले ही हमारे फ़ाइल से कम 99 अक्षर, तत्काल उपलब्ध सभी डेटा के साथ read(99) रिटर्न के लिए एक कॉल है।

मैं socket.makefile से लौटाई गई फाइल ऑब्जेक्ट्स पर यह व्यवहार प्राप्त करना चाहता हूं। लेकिन अगर मैं कहता हूँ:

import socket 
ADDR = ("localhost", 12345) 

listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
listener.bind(ADDR) 
listener.listen(1) 

client = socket.create_connection(ADDR) 
cf = client.makefile("r+b", bufsize=0) 

server, client_addr = listener.accept() 
sf = server.makefile("r+b", bufsize=0) 

sf.write("Hello World!") 
sf.flush() 
print cf.read(99)   # hangs forever 

socket.makefile डॉक्स के अनुसार, "वैकल्पिक मोड और bufsize तर्क में निर्मित फ़ाइल() फ़ंक्शन द्वारा के रूप में एक ही तरीके से समझा जाता है।" लेकिन मेरा मूल फ़ाइल उदाहरण तब भी काम करता है जब मैं open(fname, "r+b", 0) कहता हूं, जबकि मैं सभी उपलब्ध डेटा को सॉकेट छद्म फ़ाइल के साथ निर्दिष्ट बाइट्स तक वापस करने का कोई तरीका नहीं समझ सकता।

यह अगर मैं का उपयोग पूरी तरह से अच्छी तरह से काम करने लगता है socket.recv:

import socket 
ADDR = ("localhost", 12345) 

listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
listener.bind(ADDR) 
listener.listen(1) 

client = socket.create_connection(ADDR) 
server, client_addr = listener.accept() 

server.sendall("Hello World!") 
print client.recv(99)   # prints "Hello World!" 

तो वहाँ socket.makefile के साथ इस काम करने के लिए किसी भी तरह से है, या "उन्नत" कार्यक्षमता इस तरह आसानी से उपलब्ध नहीं है?

संपादित करें:

import socket 
ADDR = ("localhost", 12345) 

listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
listener.bind(ADDR) 
listener.listen(1) 

client = socket.create_connection(ADDR) 
cf = client.makefile("rwb", buffering=0) 

server, client_addr = listener.accept() 
sf = server.makefile("rwb", buffering=0) 

sf.write(b"Hello World!") 
sf.flush() 
print(cf.read(99))   # prints "Hello World!" 

मैं अभी तक स्रोत कोड में खोदा नहीं किया है इन के बीच अंतर यह पता लगाने की: अजगर 3.2 सही ढंग से व्यवहार करने के लिए, हालांकि socket.makefile को तर्क वाक्य विन्यास बदल है प्रकट होता है लगता है दो संस्करण, लेकिन यह एक संकेत हो सकता है।

+0

@BrandonRhodes मेरा मानना ​​है कि इस सॉकेट 'sock.shutdown (SHUT_WR)' – Mazyod

उत्तर

22

समस्या यह है कि client.read() वर्तमान स्थिति से EOF पर पढ़ने की कोशिश करता है, लेकिन सॉकेट के लिए ईओएफ केवल तब दिखाई देता है जब दूसरी तरफ कनेक्शन बंद हो जाता है। दूसरी तरफ recv पढ़ने के लिए तैयार किसी भी डेटा को वापस कर देगा (यदि कोई है), या अवरोध और टाइमआउट सेटिंग्स के अनुसार ब्लॉक कर सकते हैं।

यह एक करने के लिए की तुलना करें:

import socket 
ADDR = ("localhost", 12345) 

listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
listener.bind(ADDR) 
listener.listen(1) 

client = socket.create_connection(ADDR) 
cf = client.makefile("r+b", bufsize=0) 

server, client_addr = listener.accept() 
sf = server.makefile("r+b", bufsize=0) 

sf.write("Hello World!") 
sf.flush() 
sf.close() 
server.close() 
print cf.read(99)   # does not hang 
+1

इस उत्तर यह बिल्कुल सही हो जाता है बंद करने के लिए एक और व्यवहार्य विकल्प है: एक फ़ाइल के वैचारिक बराबर ईओएफ एक सॉकेट बंद है(); यह जवाब स्वीकार किया जाना चाहिए। –

+0

यदि आप केवल उपलब्ध डेटा को पढ़ते हैं तो यह अभी भी लटका होगा? मुझे लगता है कि एक बार 99 बाइट्स आते हैं। पढ़ना अवरुद्ध हो जाएगा क्योंकि यह w/e IO को 99 बाइट्स या ईओएफ देने के लिए इंतजार कर रहा है। – Kaliber64

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

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