2011-02-19 14 views
5

असल में, मेरे पास एक यूआरएल है जो नए संदेश पोस्ट किए जाने पर चैट रूम से एक्सएमएल अपडेट स्ट्रीम करता है। मैं उस यूआरएल को इनपुटस्ट्रीम में बदलना चाहता हूं और जब तक कनेक्शन बनाए रखा जाता है तब तक इसे पढ़ना जारी रखता है और जब तक मैंने Thread.interrupt() नहीं भेजा है। जिस समस्या का मैं अनुभव कर रहा हूं वह यह है कि स्ट्रीम से पढ़ने के लिए सामग्री होने पर BufferedReader.ready() सच साबित नहीं होता है।एक HttpsURL कनेक्शन से जावा गैर-अवरुद्ध इनपुटस्ट्रीम कैसे बनाएं?

मैं निम्नलिखित कोड का उपयोग कर रहा: जब मैं कोड चलाने

BufferedReader buf = new BufferedReader(new InputStreamReader(ins)); 


String str = ""; 
while(Thread.interrupted() != true) 
{ 
    connected = true; 
    debug("Listening..."); 

    if(buf.ready()) 
    { 
     debug("Something to be read."); 
     if ((str = buf.readLine()) != null) { 
      // str is one line of text; readLine() strips the newline character(s) 
      urlContents += String.format("%s%n", str); 
      urlContents = filter(urlContents); 
     } 
    } 

    // Give the system a chance to buffer or interrupt. 
    try{Thread.sleep(1000);} catch(Exception ee) {debug("Caught thread exception.");} 
} 

, और चैट रूम में कुछ पोस्ट, buf.ready() कभी सच हो जाता है, लाइनों पढ़ा जा रहा कभी नहीं हो जाती है। हालांकि, अगर मैं "buf.ready()" भाग छोड़ देता हूं और सीधे लाइनों को पढ़ता हूं, तो लाइनों को पढ़ने तक यह आगे की कार्रवाई को अवरुद्ध करता है।

मैं या तो कैसे कर सकता हूं) buf.ready() को सही करने के लिए मिलता है, या बी) ब्लॉकिंग को रोकने के लिए इस तरह से ऐसा करें?

अग्रिम धन्यवाद, जेम्स

+1

प्रत्येक कनेक्शन को अलग थ्रेड में विभाजित किया जाना चाहिए। – Nick

उत्तर

7

Reader.ready() अवरुद्ध किए बिना डेटा को पढ़ा जा सकता है जब सच हो जाता है। अवधि। InputStreams और Readers अवरुद्ध कर रहे हैं। अवधि। यहां सबकुछ डिज़ाइन के रूप में काम कर रहा है। यदि आप इन एपीआई के साथ अधिक सहमति चाहते हैं तो आपको एकाधिक धागे का उपयोग करना होगा। या Socket.setSoTimeout() और HttpURLConnection में इसके निकट संबंध।

+0

मुझे पता है कि मैं चीज़ों को धागे में विभाजित कर सकता हूं ... यह कोड पहले से ही अपने धागे (चलने योग्य) ऑब्जेक्ट में है। मैं चाहता हूं कि कुछ प्रकार के बाधाओं को भेजकर थ्रेड को कैसे रोकें। जब इनपुट स्ट्रीम स्ट्रीम में अधिक डेटा प्रकाशित होने की प्रतीक्षा कर रहा है, तो यह thread.interrupts सहित अन्य सभी को अवरुद्ध करता है। – Warkior

+0

क्या आप ऐसी स्थिति का वर्णन कर सकते हैं जहां Reader.ready() सत्य वापस लौटने में सक्षम होगा, अगर (जैसा कि आपने कहा) पाठक स्वाभाविक रूप से अवरुद्ध हैं? आपने जो कहा है उसके आधार पर, ऐसा लगता है कि Reader.ready() एक बेकार विधि है। – Warkior

+0

यदि डेटा पहले से ही उपलब्ध है, तो तैयार() सत्य लौटाता है और एक पाठक ब्लॉक नहीं करेगा। यदि कोई डेटा उपलब्ध नहीं है, तो तैयार() झूठी वापसी करता है और एक पाठक ब्लॉक करेगा। – EJP

0

आप जावा NIO पुस्तकालय जो गैर अवरुद्ध I/O क्षमता प्रदान करता है का उपयोग कर सकते हैं। विवरण और नमूना कोड के लिए इस आलेख पर एक नज़र डालें: http://www.drdobbs.com/java/184406242

+0

ऐसा लगता है कि इसका मतलब है कि मैं थ्रेड को टाइम-आउट करने के लिए अवरुद्ध कर रहा था, अवरुद्ध कनेक्शन तोड़ रहा था। इसे आज़माएं। धन्यवाद। – Warkior

+0

हम्म। अभी तक अवरुद्ध थ्रेड को सही तरीके से बाधित करने का कोई तरीका नहीं ढूंढ पाया है। शायद मैं इसे सही नहीं कर रहा हूँ। – Warkior

4

आईओओ को अनब्लॉक करने के लिए इनपुटस्ट्रीम और रीडर (या आउटपुटस्ट्रीम/राइटर) का उपयोग न करें, लेकिन java.nio.* कक्षाओं का उपयोग करें, इस मामले में SocketChannel (और एक वर्णसेट डीकोडर अतिरिक्त)।


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

विशेष रूप से कैसे एक https यूआरएल के लिए एक सॉकेट चैनल बनाने के लिए की तलाश में: अपनी टिप्पणी के जवाब के रूप।

सॉकेट (और सॉकेट चैनल्स) परिवहन परत (टीसीपी), एक (या दो) स्तर पर HTTP परत जैसे अनुप्रयोग परत प्रोटोकॉल पर काम करते हैं। तो आप एक https url पर सॉकेट चैनल नहीं बना सकते हैं।

आपको इसके बजाय सही सर्वर पर सही सॉकेट-चैनल खोलना होगा और सही पोर्ट (443 अगर यूआरआई में कुछ और नहीं दिया गया है), क्लाइंट मोड में एक एसएसएलईजीएनएन (javax.net.ssl ​​में) बनाएं, फिर पढ़ें चैनल से डेटा, इसे एसएसएल इंजन और अन्य तरीकों से खिलाकर, और अपने एसएसएलईजीएनएएन से सही HTTP प्रोटोकॉल लाइनों को भेज/प्राप्त करें, हमेशा यह जानने के लिए रिटर्न वैल्यू की जांच करें कि वास्तव में कितने बाइट वास्तव में संसाधित किए गए थे और क्या होगा लेने के लिए अगला कदम।

यह is quite complicated (मैंने इसे एक बार किया), और आप वास्तव में ऐसा नहीं करना चाहते हैं यदि आप एक सर्वर को लागू नहीं कर रहे हैं जिसमें एक ही समय में जुड़े कई क्लाइंट हैं (जहां आप के लिए एक थ्रेड नहीं हो सकता प्रत्येक कनेक्शन)। इसके बजाय, अपने अवरुद्ध इनपुटस्ट्रीम के साथ रहें जो आपके URL कनेक्शन से पढ़ता है, और इसे केवल एक अतिरिक्त थ्रेड में रखता है जो आपके शेष एप्लिकेशन को बाधित नहीं करता है।

+0

पर आने वाले सभी तक तब तक ब्लॉक करेगा जब उस पर एक अच्छा ट्यूटोरियल मिलेगा? – Warkior

+0

विशेष रूप से एक https url में सॉकेट चैनल बनाने का तरीका ढूंढना। – Warkior

+1

@Warkior: मेरा अंतिम संपादन देखें - आप वास्तव में ऐसा नहीं करना चाहते हैं। –

0

चैनलों का उपयोग कर कोई HTTP/HTTPS कार्यान्वयन नहीं है।एक गैर-अवरुद्ध तरीके से एक प्रेस्पिसप्लोकनेक्शन से इनपुटस्ट्रीम पढ़ने का कोई तरीका नहीं है। आपको या तो किसी तृतीय पक्ष lib का उपयोग करना होगा या सॉकेट चैनल पर http को लागू करना होगा।

0
import java.io.IOException; 
import java.io.InputStream; 
import java.util.Arrays; 

/** 
* This code demonstrates non blocking read from standard input using separate 
* thread for reading. 
*/ 
public class NonBlockingRead { 

    // Holder for temporary store of read(InputStream is) value 
    private static String threadValue = ""; 

    public static void main(String[] args) throws InterruptedException { 

     NonBlockingRead test = new NonBlockingRead(); 

     while (true) { 
      String tmp = test.read(System.in, 100); 
      if (tmp.length() > 0) 
       System.out.println(tmp); 
      Thread.sleep(1000); 
     } 
    } 

    String read(final InputStream is, int timeout) { 
     // Start reading bytes from stream in separate thread 
     Thread thread = new Thread() { 
      public void run() { 
       byte[] buffer = new byte[1024]; // read buffer 
       byte[] readBytes; // holder of actually read bytes 
       try { 
        // Read available bytes from stream 
        int size = is.read(buffer); 
        if (size > 0) { 
         if (size > 1) 
          readBytes = Arrays.copyOf(buffer, size - 1); 
         else 
          readBytes = new byte[0]; 
         // and save read value in static variable 
         setValue(new String(readBytes, "UTF-8")); 
        } 
       } catch (IOException e) { 
        System.err.println("Data reading error: " + e); 
       } 
      } 
     }; 
     thread.start(); // Start thread 
     try { 
      thread.join(timeout); // and join it with specified timeout 
     } catch (InterruptedException e) { 
      System.err.println("Data were note read in " + timeout + " ms"); 
     } 
     return getValue(); 
    } 

    private synchronized void setValue(String value) { 
     threadValue = value; 
    } 

    private synchronized String getValue() { 
     String tmp = new String(threadValue); 
     setValue(""); 
     return tmp; 
    } 

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