2014-09-03 5 views
6

मुझे लगता है कि मैं std :: io :: टीसीपीस्ट्रीम के साथ संघर्ष कर रहा हूं। मैं वास्तव में किसी अन्य सिस्टम के साथ एक टीसीपी कनेक्शन खोलने की कोशिश कर रहा हूं लेकिन नीचे दिया गया कोड वास्तव में समस्या का अनुकरण करता है।जंग लगातार टीसीपीस्ट्रीम

मेरे पास एक टीसीपी सर्वर है जो खोलने पर टीसीपीस्ट्रीम को "हैलो वर्ल्ड" लिखता है और फिर कनेक्शन को खोलने के लिए लूप करता है।

fn main() { 
    let listener = io::TcpListener::bind("127.0.0.1", 8080); 
    let mut acceptor = listener.listen(); 
    for stream in acceptor.incoming() { 

    match stream { 
     Err(_) => { /* connection failed */ } 
     Ok(stream) => spawn(proc() { 
     handle(stream); 
     }) 
    } 
    } 
    drop(acceptor); 
} 

fn handle(mut stream: io::TcpStream) { 
    stream.write(b"Hello Connection"); 
    loop {} 
} 

सभी क्लाइंट कनेक्शन से एक बाइट पढ़ने और इसे प्रिंट करने का प्रयास करता है।

fn main() { 
    let mut socket = io::TcpStream::connect("127.0.0.1", 8080).unwrap(); 
    loop { 
     match socket.read_byte() { 
     Ok(i) => print!("{}", i), 
     Err(e) => { 
      println!("Error: {}", e); 
      break 
     } 
     } 
    } 
} 

अब समस्या मेरे मुवक्किल पढ़ने पर अवरुद्ध रहता है जब तक मैं सर्वर को मारने या टीसीपी कनेक्शन बंद है। यह वही नहीं है जो मुझे चाहिए, मुझे बहुत लंबे समय तक एक टीसीपी कनेक्शन खोलना होगा और क्लाइंट और सर्वर के बीच संदेश भेजना होगा। मैं यहाँ क्या गलत समझ रहा हूँ? मेरे पास वास्तविक प्रणाली के साथ एक ही समस्या है जिसके साथ मैं संचार कर रहा हूं - कनेक्शन को मारने के बाद ही मैं अनब्लॉक हो जाता हूं।

उत्तर

7

दुर्भाग्य से, जंग में अब एसिंक्रोनस I/O के लिए कोई सुविधा नहीं है। वहां are स्थिति को सुधारने के कुछ प्रयास हैं, लेकिन वे अभी तक पूरी तरह से दूर हैं। यही है, वास्तव में एसिंक्रोनस I/O संभव बनाने की इच्छा है (प्रस्तावों में एक ही समय में I/O स्रोतों और चैनलों पर चयन करना शामिल है, जो एक I/O ऑपरेशन के अंदर अवरुद्ध किए गए कार्यों को अनुमति देता है जो किसी ईवेंट के माध्यम से अवरुद्ध होते हैं चैनल, हालांकि यह स्पष्ट नहीं है कि यह सभी समर्थित प्लेटफ़ॉर्म पर कैसे कार्यान्वित किया जाना चाहिए), लेकिन अभी भी बहुत कुछ करना है और अब तक वास्तव में उपयोग करने योग्य कुछ भी नहीं है, जहां तक ​​मुझे पता है।

हालांकि, आप कुछ हद तक टाइमआउट के साथ इसका अनुकरण कर सकते हैं। यह सबसे अच्छा समाधान से बहुत दूर है, लेकिन यह काम करता है। यह इस (मेरी कोड आधार से सरलीकृत उदाहरण) की तरह लग सकता है:

let mut socket = UdpSocket::bind(address).unwrap(); 

let mut buf = [0u8, ..MAX_BUF_LEN]; 
loop { 
    socket.set_read_timeout(Some(5000)); 
    match socket.recv_from(buf) { 
     Ok((amt, src)) => { /* handle successful read */ } 
     Err(ref e) if e.kind == TimedOut => {} // continue 
     Err(e) => fail!("error receiving data: {}", e) // bail out 
    } 

    // do other work, check exit flags, for example 
} 

यहाँ recv_fromTimedOut करने के लिए kind सेट के साथ IoError वापस आ जाएगी अगर वहाँ कोई डेटा recv_from कॉल के अंदर 5 सेकंड के दौरान सॉकेट पर उपलब्ध है। आपको प्रत्येक लूप पुनरावृत्ति के अंदर टाइमआउट को रीसेट करने की आवश्यकता है क्योंकि यह टाइमआउट की तुलना में "समय सीमा" की तरह अधिक है - जब यह समाप्त हो जाती है, तो सभी कॉल टाइमआउट त्रुटि के साथ विफल हो जाएंगी।

यह निश्चित रूप से ऐसा नहीं होना चाहिए, लेकिन जंग वर्तमान में कुछ भी बेहतर नहीं प्रदान करता है। कम से कम यह अपना काम करता है।

अद्यतन

अब एक अतुल्यकालिक घटना पाश और नेटवर्क मैं/हे उस पर आधारित बनाने के लिए एक प्रयास है। इसे mio कहा जाता है। यह शायद अतुल्यकालिक I/O के लिए एक अच्छा अस्थायी (या यहां तक ​​कि स्थायी, जो जानता है) समाधान हो सकता है।

+0

ठीक है तो मैं उचित एसिंक्रोनस I/O ... बमर करने में सक्षम नहीं होगा। लेकिन कनेक्शन बंद होने तक मैं टीसीपीस्ट्रीम से डेटा क्यों नहीं पढ़ सकता? क्या यह ईओएफ तक सभी डेटा बफर करने के लिए लागू किया गया है? – Upio

+0

@Upio, क्या आपने यह नहीं कहा: "अब समस्या यह है कि जब तक मैं सर्वर को मारता या टीसीपी कनेक्शन बंद नहीं करता तब तक मेरा क्लाइंट पढ़ने पर अवरुद्ध रहता है"? यह "कनेक्शन बंद होने तक टीसीपीस्ट्रीम से डेटा पढ़ रहा है", है ना? वैसे भी, 'टीसीपीस्ट्रीम' एक ['रीडर'] है (http://doc.rust-lang.org/std/io/trait.Reader.html), इसलिए इसमें [' read_to_end() '] है (http://doc.rust-lang.org/std/io/trait.Reader.html#method.read_to_end) विधि जो सभी स्ट्रीम को बंद होने तक खपत करती है। क्या आपको इसकी आवश्यकता है? –

+0

क्षमा करें अगर मैं अस्पष्ट था, मुझे पहले से ही पता है कि पाठक के साथ कैसे बातचीत करें। मैं सिर्फ यह समझना चाहूंगा कि कनेक्शन बंद होने तक ग्राहक पक्ष पर कोई डेटा क्यों नहीं पढ़ा जाता है। यहां तक ​​कि मैं read_byte() का उपयोग करता हूं, यह कनेक्शन समाप्त होने तक ब्लॉक करता है।यह आंतरिक रूप से कैसे काम कर रहा है? – Upio