繁体   English   中英

如何解锁 Android 上的 InputStream.read()?

[英]How to unblock InputStream.read() on Android?

我有一个线程,其中循环调用InputStreamread()方法。 当没有更多字节要读取时,stream 将阻塞,直到新数据到达。

如果我从不同的线程调用InputStream上的close() ,则 stream 将关闭,但阻塞的read()调用仍然被阻塞。 我假设read()方法现在应该返回值-1以指示 stream 的结束,但事实并非如此。 相反,它会再阻塞几分钟,直到发生 tcp 超时。

如何解除对close()调用的阻止?

编辑:

显然,当阻塞read()调用对应的 ZF7B44CFFAFD5C52223D5498196C8A2E7BZ 或套接字为close()时,常规 JRE 将立即抛出SocketException 但是,我正在使用的 Android Java 运行时不会。

任何有关 Android 环境解决方案的提示将不胜感激。

只有在有可用数据时才调用read()

做这样的事情:

    while( flagBlock )
    {
        if( stream.available() > 0 )
        {
            stream.read( byteArray );
        }
    }

设置flagBlock以停止读取。

当另一端关闭连接时,您的 ZF7B44CFFAFD5C52223D5498196C8A2E7BZ 将在 read() 上返回 -1。 如果您无法触发另一端关闭连接,例如通过关闭 output stream,您可以关闭套接字,这将在阻塞的 read() 线程中导致 IOException。


您能否提供一个简短的示例来重现您的问题?

ServerSocket ss = new ServerSocket(0);
final Socket client = new Socket("localhost", ss.getLocalPort());
Socket server = ss.accept();
Thread t = new Thread(new Runnable() {
    public void run() {
        int ch;
        try {
            while ((ch = client.getInputStream().read()) != -1)
                System.out.println(ch);
        } catch (SocketException se) {
            System.out.println(se);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
});
t.start();
server.getOutputStream().write("hi\n".getBytes());
Thread.sleep(100);
client.close();
t.join();

server.close();
ss.close();

印刷

104
105
10
java.net.SocketException: Socket closed

请参阅Java 实践中的并发性,了解在使用 sockets 时取消线程的非常好的系统。 它使用一个特殊的执行器 ( CancellingExecutor ) 和一个特殊的 Callable ( SocketUsingTask )。

我们遇到了同样的问题:切换网络时也不例外(例如,下载时从 3G 切换到 WiFi)。

我们正在使用http://www.androidsnippets.com/download-an-http-file-to-sdcard-with-progress-notification中的代码,除了在某些情况下网络连接丢失时,它运行良好。

解决方案是指定超时值,将标准设置为 0(意思是:无限等待)。

    HttpURLConnection c = (HttpURLConnection) u.openConnection();
    c.setRequestMethod("GET");
    c.setDoOutput(true);
    c.setReadTimeout(1000);
    c.connect();

尝试适合您的超时值。

我在三星 2.3 上遇到过这样的问题。 从 3G 切换到 Wifi 时 InputStream.read() 方法块。 我尝试了该主题的所有提示。 没有任何帮助。 从我的角度来看,这是特定于设备的问题,因为它应该抛出 IOException 由于javadoc 我的解决方案是监听 android 广播android.net.conn.CONNECTIVITY_CHANGE并关闭来自另一个线程的连接,这将导致阻塞线程中的 IOException。

这是代码示例:

下载Thread.java

private volatile boolean canceled;

private volatile InputStream in;

private boolean downloadFile(final File file, final URL url, long totalSize) {
    OutputStream out = null;
    try {
        Log.v(Common.TAG, "DownloadThread: downloading to " + file);

        in = (InputStream) url.getContent();
        out = new FileOutputStream(file);

        return copy(out, totalSize);
    } catch (Exception e) {
        Log.e(Common.TAG, "DownloadThread: Exception while downloading. Returning false ", e);
        return false;
    } finally {
        closeStream(in);
        closeStream(out);
    }
}

public void cancelDownloading() {
    Log.e(Common.TAG, "DownloadThread: cancelDownloading ");
    canceled = true;
    closeStream(in); //on my device this is the only way to unblock thread
}

private boolean copy(final OutputStream out, long totalSize) throws IOException {
    final int BUFFER_LENGTH = 1024;
    final byte[] buffer = new byte[BUFFER_LENGTH];
    long totalRead = 0;
    int progress = 0;
    int read;

    while (!canceled && (read = in.read(buffer)) != -1) {
        out.write(buffer, 0, read);
        totalRead += read;
    }
    return !canceled;
}

您可以使用java.nio package。 NIO 代表非阻塞 IO。 这里的调用(比如说读和写)没有被阻止。 这样您就可以关闭 stream。

您可以在此处查看示例程序。 方法: processRead

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM