简体   繁体   English

中断Java DataInputStream readFully()

[英]Interrupting Java DataInputStream readFully()

I have a Java applet that streams video (MJPEG) from a server. 我有一个Java applet,它从服务器流式传输视频(MJPEG)。 I wrote a proxy server in C# (Windows service) to put between the applet and multiple video servers. 我用C#(Windows服务)编写了一个代理服务器,放在applet和多个视频服务器之间。 A HTML/CSS/Js frontend is used along with the Java applet. HTML / CSS / Js前端与Java applet一起使用。 All functionality works fine (finally!!!), except one thing. 所有功能都可以正常工作(最后!!!),除了一件事。

The video server allows you to play back recorded video through a REST interface. 视频服务器允许您通过REST界面播放录制的视频。 When the clip is done, the server leaves the connection open in case you want to send it commands like rewind or seek. 剪辑完成后,服务器将打开连接,以防您想要发送倒带或搜索等命令。 The clip is being played fine in the applet until the end. 该剪辑在小程序中正常播放,直到结束。 If you try to start a new clip (which entails sending a command from Javscript to the applet), the browser freezes up. 如果您尝试启动一个新剪辑(需要从Javscript向applet发送命令),浏览器会冻结。 However, subsequent commands that would use the same connection work, such as play, pause, and seek. 但是,后续使用相同连接的命令会起作用,例如播放,暂停和搜索。 If I stop the windows service, the browser becomes responsive again. 如果我停止Windows服务,浏览器将再次响应。

This is what I'm assuming is happening: The clip ends (or is paused); 这就是我假设正在发生的事情:剪辑结束(或暂停); no more data is sent but the connection is still active. 不再发送数据但连接仍处于活动状态。 The applet is waiting on the proxy for the next frame, but the proxy is waiting on the video server for the next frame, which is not going to send any more data. applet正在等待下一帧的代理,但是代理正在视频服务器上等待下一帧,这不会再发送任何数据。

This is the code in a while loop that reads each frame 这是读取每个帧的while循环中的代码

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

I need to interrupt this code somehow. 我需要以某种方式中断此代码。

When a new video clip is selected in the HTML frontend, we notify the applet, which calls disconnect() on the CameraStream class. 当在HTML前端中选择新的视频片段时,我们通知applet,它在CameraStream类上调用disconnect()。 This is that function: 这就是这个功能:

// 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);
        }
    }
}

To test this, I let a quick clip play and run to the end. 为了测试这个,我让一个快速剪辑播放并运行到最后。 I then select a new clip. 然后我选择一个新剪辑。 In my Java console, I get the output disconnect called. 在我的Java控制台中,我得到了输出disconnect called. but I don't get the subsequent closed. 但我不会随后closed. message, nor does that generic Exception get caught. 消息,也不会捕获该通用异常。 When I stop the Windows service, I finally get the closed. 当我停止Windows服务时,我终于closed. message, so it seems like inputStream.close(); 消息,所以看起来像inputStream.close(); is blocking. 阻止。

So I guess my question is how can I stop the blocking? 所以我想我的问题是如何阻止阻止? Is the readFully(img) call blocking? readFully(img)调用是否阻塞? Or is it the disconnect function (as suggested by the console output I get)? 或者是断开功能(我得到的控制台输出建议)?

edit: just to clarify, I wrote the Java applet, HTML, CSS, Javascript, and C# proxy server, so I have access to all of that code. 编辑:为了澄清,我编写了Java applet,HTML,CSS,Javascript和C#代理服务器,因此我可以访问所有代码。 The only code I can't modify is that of the REST interface on the video server. 我无法修改的唯一代码是视频服务器上的REST接口。

edit2: i meant to make bounty for this post https://stackoverflow.com/questions/12219758/proxy-design-pattern edit2:我打算为这篇文章做出赏赐https://stackoverflow.com/questions/12219758/proxy-design-pattern

In general, Java I/O methods block. 通常,Java I / O方法会阻塞。 The best solution appears to be to create another thread for reading the data and using NIO buffers. 最好的解决方案似乎是创建另一个线程来读取数据和使用NIO缓冲区。 Example of NIO-based read (warning: untested!): 基于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);

This code creates a Channel from the InputStream and uses the Channel to read data. 此代码从InputStream创建一个Channel ,并使用Channel读取数据。 The JavaDoc for the ReadableByteChannel.read(ByteBuffer) function says that interrupting the thread that contains the call to inChannel.read(buf) will stop the read. ReadableByteChannel.read(ByteBuffer)函数的JavaDoc表示,中断包含对inChannel.read(buf)的调用的线程将停止读取。

You will have to adapt this code, I just pulled it out of my head. 您将不得不调整此代码,我只是把它从我的头脑中拉出来。 Good luck! 祝好运!

I finally figured out the answer: 我终于找到了答案:

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);
        }
    }
}

Even though I'm using an HttpUrlConnection, which is one way and doesn't have an output stream, trying to close the output stream raised an exception and for some reason made it all work. 即使我正在使用HttpUrlConnection,这是一种方式而且没有输出流,尝试关闭输出流引发了异常,并且出于某种原因使其全部工作。

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

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