Каналы дейтаграмм не пишутся на Java - PullRequest
2 голосов
/ 13 июля 2011

Проще говоря, я могу получать данные из подключенного сокета примерно через 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);
    }
}

1 Ответ

3 голосов
/ 14 июля 2011

Я полагаю, что вы испортили интерес к вашему событию при первой записи с помощью этой строки:

channel.register(selector, SelectionKey.OP_READ);

За документацию , это приводит к сбросу только на OP_READ.

Edit 0:

За ваш комментарий - да, я думаю, вам следует полностью удалить эту строку, и не рассматривайте случаи чтения и записи как альтернативы.В общем случае сокет может быть доступен для чтения и записи одновременно.Итак, сейчас происходит то, что регистр записи предотвращает регистр чтения, поскольку сокет UDP всегда доступен для записи (в отличие от TCP, который буферизует исходящие данные).

Поэтому я предлагаю не включать OP_WRITEв этот набор событий, но обрабатывайте запись каким-либо другим способом, скажем, по таймеру, или после каждого чтения, или в любом другом смысле, который имеет смысл для вашего приложения.

Надеюсь, это поможет.

...