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

War*_*ior 7 java inputstream nonblocking

基本上,我有一个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.");}
}
Run Code Online (Sandbox Code Playgroud)

当我运行代码并将某些内容发布到聊天室时,buf.ready()永远不会成为现实,从而导致行不会被读取.但是,如果我跳过"buf.ready()"部分并直接读取行,它会阻止进一步操作直到读取行.

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

詹姆斯,先谢谢你

use*_*421 10

如何创建Java非阻塞 InputStream

你不能.你的问题体现了矛盾.Java中的Streams是阻塞的.因此,没有"非阻塞InputStream" 这样的东西.

Reader.ready()在不阻塞的情况下读取数据时返回true.期.InputStreams并且Readers正在阻止.期.这里的一切都按设计工作.如果您希望使用这些API更加并发,则必须使用多个线程.或者Socket.setSoTimeout()它和它的近似关系HttpURLConnection.


Paŭ*_*ann 5

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


编辑:作为您评论的答案:

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

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

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

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