2

簡単に言うと、接続されたソケットから、起動してから約10秒後までデータを受信できます。これを修正する解決策は、データストリームを継続するために「クライアント」(ARDrone)にデータを送信することです。そうしないと、電話へのデータの送信が停止します。ただし、私の現在のコードは、何らかの理由で、最初の接続時にのみクライアント(ARDrone)にデータを書き込み、その後は書き込みません。ソケットが通信している後もARDroneにデータを送信し続けるために必要です。

通話を移動しようとしましたchannel.register()が、必要に応じてARDroneにデータを送信することはできませんでした。

接続の作成:

channel = DatagramChannel.open();
channel.configureBlocking(false);
channel.socket().bind(new InetSocketAddress(video_port));
channel.connect(new InetSocketAddress(drone_addr, video_port));

selector = Selector.open();
channel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);

これが現在の送受信データ機能です。

public void run() {
    try {
        ByteBuffer inbuf = ByteBuffer.allocate(BUFSIZE);
        done = false;
        while (!done) {
            selector.select();
        if (done) {
            disconnect();
            break;
        }
        Set readyKeys = selector.selectedKeys();
        Iterator iterator = readyKeys.iterator();
        while (iterator.hasNext()) {
            SelectionKey key = (SelectionKey) iterator.next();
            iterator.remove();
            if (key.isWritable()) {
                byte[] trigger_bytes = { 0x01, 0x00, 0x00, 0x00 };
                ByteBuffer trigger_buf = ByteBuffer.allocate(trigger_bytes.length);
                trigger_buf.put(trigger_bytes);
                trigger_buf.flip();
                channel.write(trigger_buf);
                channel.register(selector, SelectionKey.OP_READ);
            } else if (key.isReadable()) {
                inbuf.clear();
                int len = channel.read(inbuf);

                if (len > 0) {
                    inbuf.flip();
                    final BufferedVideoImage vi = new BufferedVideoImage();;
                    vi.addImageStream(inbuf);
                    drone.videoFrameReceived(0, 0, vi.getWidth(), vi.getHeight(), vi.getJavaPixelData(), 0, vi.getWidth());
                }
            }
        }

    } catch (Exception e) {
        drone.changeToErrorState(e);
    }
}
4

1 に答える 1

3

私はあなたがこの行で最初の書き込みであなたのイベントの興味を壊したと信じています:

channel.register(selector, SelectionKey.OP_READ);

ドキュメントによると、これはそれをのみにリセットしますOP_READ

編集0:

あなたのコメントによると-はい、私はあなたがその行を完全に削除するべきであり、読み取りと書き込みのケースを代替として扱わないべきだと思います。一般に、ソケットは読み取りと書き込みを同時に行うことができます。したがって、現在起こっていることは、UDPソケットは常に書き込み可能であるため(送信データをバッファリングするTCPに対して)、書き込みケースが読み取りケースを防ぐことです。

したがって、私の提案は、OP_WRITEそのイベントセットにまったく含めないで、タイマーや各読み取り後など、アプリにとって意味のある他の方法で書き込みを処理することです。

お役に立てれば。

于 2011-07-13T20:46:37.360 に答える