如何从HttpsURLConnection创建Java非阻塞InputStream?

基本上,我有一个URL,可以在发布新消息时从聊天室传输xml更新。 我想将该URL转换为InputStream并继续读取它,只要保持连接并且只要我没有发送Thread.interrupt()。 我遇到的问题是,当从流中读取内容时,BufferedReader.ready()似乎不会成为现实。

我正在使用以下代码:

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()”部分并直接读取行,它会阻止进一步的操作直到读取行。

我如何a)让buf.ready()返回true,或者b)以防止阻塞的方式执行此操作?

先谢谢你,詹姆斯

如何创建Java非阻塞InputStream

你不能。 你的问题在术语上体现了矛盾。 Java中的Streams是阻塞的。 因此,没有non-blocking InputStream`’。

当无阻塞地读取数据时, Reader.ready()返回true。 期。 InputStreamsReaders正在阻塞。 期。 这里的一切都按设计工作。 如果您希望使用这些API实现更多并发性,则必须使用多个线程。 或者Socket.setSoTimeout()及其在HttpURLConnection近似关系。

对于非阻塞IO,不要使用InputStream和Reader(或OutputStream / Writer),而是使用java.nio.*类,在本例中为SocketChannel (以及另外的CharsetDecoder)。


编辑:作为评论的答案:

专门寻找如何创建一个https url的套接字通道。

套接字(以及SocketChannels)在传输层(TCP)上工作,在HTTP等应用层协议之下的一个(或两个)级别。 因此, 您无法为httpsurl创建套接字通道

你需要打开一个Socket-Channel到正确的服务器和正确的端口(443如果URI中没有给出其他内容),在客户端模式下创建一个SSLEngine(在javax.net.ssl中),然后从通道读取数据将其提供给SSL引擎,反之亦然,并向/从SSLEngine发送/获取正确的HTTP协议行,始终检查返回值以了解实际处理了多少字节以及下一步将是什么采取。

这是非常复杂的 (我曾经做过一次),如果你没有实现同时连接大量客户端的服务器(你不能为每个连接都有一个线程),你真的不想这样做)。 相反, 请使用阻塞的InputStream ,它从URLConnection中读取,并将其简单地放在一个不会妨碍应用程序其余部分的备用线程中。

您可以使用提供非阻塞I / Ofunction的Java NIO库。 请查看本文以获取详细信息和示例代码: http : //www.drdobbs.com/java/184406242 。

使用Channels没有HTTP / HTTPS实现。 无法以非阻塞方式从httpurlconnaction读取输入流。 您必须自己使用第三方库或通过SocketChannel实现http。

 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); } } /** * Non blocking read from input stream using controlled thread * * @param is * — InputStream to read * @param timeout * — timeout, should not be less that 10 * @return */ 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 = new byte[0]; // holder of actually read bytes try { Thread.sleep(5); // Read available bytes from stream int size = is.read(buffer); if (size > 0) readBytes = Arrays.copyOf(buffer, size); // and save read value in static variable setValue(new String(readBytes, "UTF-8")); } catch (Exception e) { System.err.println("Error reading input stream\nStack trace:\n" + e.getStackTrace()); } } }; 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; } }