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

时间:2011-02-19 06:41:22

标签: 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.");}
}

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

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

提前致谢, 詹姆斯

5 个答案:

答案 0 :(得分:9)

  

如何创建Java非阻塞InputStream

你做不到。你的问题体现了矛盾。 Java中的Streams是阻塞的。因此,没有“非阻塞InputStream”这样的东西。

当无阻塞地读取数据时,

Reader.ready()返回true。期。 InputStreamsReaders正在阻止。期。这里的一切都按设计工作。如果您希望使用这些API更加并发,则必须使用多个线程。或Socket.setSoTimeout()及其HttpURLConnection附近的关系。

答案 1 :(得分:5)

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


编辑:作为对您评论的回答:

  

专门查找如何创建https网址的套接字通道。

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

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

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

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

答案 4 :(得分:-1)

def create_dictionary(clean_word_list):
 word_count = {}
 for word in clean_word_list:
    if word in word_count:
        word_count[word] += 1
    else:
        word_count[word] = 1
 for key, value in sorted(word_count.items(), key=operator.itemgetter(1)):
    print(key, value)