9

サーバーからビデオ (MJPEG) をストリーミングする Java アプレットがあります。アプレットと複数のビデオ サーバーの間に配置するプロキシ サーバーを C# (Windows サービス) で作成しました。HTML/CSS/Js フロントエンドは、Java アプレットと共に使用されます。1 つのことを除いて、すべての機能が正常に動作します (最終的に!!!)。

ビデオ サーバーを使用すると、REST インターフェイスを介して録画したビデオを再生できます。クリップが終了すると、巻き戻しやシークなどのコマンドをサーバーに送信する場合に備えて、サーバーは接続を開いたままにします。クリップは最後までアプレットで正常に再生されています。新しいクリップを開始しようとすると (Javascript からアプレットにコマンドを送信する必要があります)、ブラウザがフリーズします。ただし、同じ接続を使用する後続のコマンド (再生、一時停止、シークなど) は機能します。Windows サービスを停止すると、ブラウザーは再び応答するようになります。

これは私が想定していることです: クリップが終了します (または一時停止されます)。これ以上データは送信されませんが、接続はまだアクティブです。アプレットはプロキシで次のフレームを待機していますが、プロキシはビデオ サーバーで次のフレームを待機しており、これ以上データを送信しません。

これは、各フレームを読み取る while ループのコードです。

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

何らかの方法でこのコードを中断する必要があります。

HTML フロントエンドで新しいビデオ クリップが選択されると、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 アプレット、HTML、CSS、Javascript、および C# プロキシ サーバーを作成したので、そのすべてのコードにアクセスできます。私が変更できない唯一のコードは、ビデオ サーバーの REST インターフェイスのコードです。

edit2:この投稿の報奨金を作るつもりでしたhttps://stackoverflow.com/questions/12219758/proxy-design-pattern

4

2 に答える 2

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てデータを読み取ります。関数のJavaDocにReadableByteChannel.read(ByteBuffer)は、呼び出しを含むスレッドを中断するとinChannel.read(buf)読み取りが停止すると書かれています。

このコードを適応させる必要があります。私は頭から引っ張り出しました。幸運を!

于 2012-09-03T21:26:00.380 に答える
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 を使用していますが、これは 1 つの方法であり、出力ストリームを持っていませんが、出力ストリームを閉じようとすると例外が発生し、何らかの理由ですべてが機能しました。

于 2012-09-06T22:01:35.803 に答える