中断Java DataInputStream readFully()

时间:2012-08-29 21:15:50

标签: java blocking datainputstream

我有一个Java applet,它从服务器流式传输视频(MJPEG)。我用C#(Windows服务)编写了一个代理服务器,放在applet和多个视频服务器之间。 HTML / CSS / Js前端与Java applet一起使用。所有功能都可以正常工作(最后!!!),除了一件事。

视频服务器允许您通过REST界面播放录制的视频。剪辑完成后,服务器将打开连接,以防您想要发送倒带或搜索等命令。该剪辑在小程序中正常播放,直到结束。如果您尝试启动一个新剪辑(需要从Javscript向applet发送命令),浏览器会冻结。但是,后续使用相同连接的命令会起作用,例如播放,暂停和搜索。如果我停止Windows服务,浏览器会再次响应。

这就是我假设正在发生的事情:剪辑结束(或暂停);不再发送数据但连接仍处于活动状态。 applet正在等待下一帧的代理,但是代理正在视频服务器上等待下一帧,这不会再发送任何数据。

这是读取每个帧的while循环中的代码

byte[] img = new byte[mContentLength];
inputStream.skipBytes(headerLen);
inputStream.readFully(img);

我需要以某种方式中断此代码。

当在HTML前端中选择新的视频片段时,我们会通知applet,它在CameraStream类上调用disconnect()。这就是这个功能:

// DataInputStream inputStream
// HttpURLConnection conn
public void disconnect() {
    System.out.println("disconnect called.");
    if(running) {
        running = false;
        try {
            // close the socket
            if(inputStream != null) {
                inputStream.close();
            }
            if(conn != null) {
                conn.disconnect();
            }
            inputStream = null;
            System.out.println("closed.");
        } catch(Exception ignored) {
            System.out.println("exc:" + ignored.getMessage());
            main.reportErrorFromThrowable(ignored);
        }
    }
}

为了测试这个,我让一个快速剪辑播放并运行到最后。然后我选择一个新剪辑。在我的Java控制台中,我得到了输出disconnect called.,但是我没有得到后续的closed.消息,也没有捕到该通用异常。当我停止Windows服务时,我终于收到了closed.消息,因此看起来inputStream.close();正在阻止。

所以我想我的问题是如何阻止阻止? readFully(img)来电是否被阻止?或者它是断开连接功能(我得到的控制台输出建议)?

编辑为了澄清,我编写了Java applet,HTML,CSS,Javascript和C#代理服务器,因此我可以访问所有代码。我无法修改的唯一代码是视频服务器上的REST接口。

edit2:我打算为此帖{4}付出赏金

2 个答案:

答案 0 :(得分:0)

通常,Java I / O方法会阻塞。最好的解决方案似乎是创建另一个线程来读取数据和使用NIO缓冲区。基于NIO的读取示例(警告:未经测试!):

// get the InputStream from somewhere (a queue possibly)
ReadableByteChannel inChannel = Channels.newChannel(inputStream);
ByteBuffer buf = ByteBuffer.allocate(mContentLength + headerLen);
inChannel.read(buf);
byte[] img = new byte[mContentLength];
inChannel.get(img, headerLen, mContentLength);

此代码从Channel创建InputStream并使用Channel来读取数据。 ReadableByteChannel.read(ByteBuffer)函数的JavaDoc表示,中断包含对inChannel.read(buf)的调用的线程将停止读取。

你必须调整这段代码,我只是把它拉出来。祝你好运!

答案 1 :(得分:0)

我终于找到了答案:

public void disconnect() {
    if(running) {
        running = false;
        try {
            try{
                // had to add this
                conn.getOutputStream().close();
            }
            catch(Exception exc){
            }
            // close the socket
            if(inputStream != null) {
                inputStream.close();
            }
            if(conn != null) {
                conn.disconnect();
            }
            inputStream = null;


        } catch(Exception ignored) {
            main.reportErrorFromThrowable(ignored);
        }
    }
}

即使我正在使用HttpUrlConnection,这是一种方式而且没有输出流,尝试关闭输出流引发了异常,并且出于某种原因使它全部工作。