Java - работа в сети - Best Practice - смешанные синхронные / асинхронные команды - PullRequest
6 голосов
/ 05 июня 2011

Я разрабатываю небольшую клиент-серверную программу на Java.

Клиент и сервер соединены через одно tcp-соединение.Большинство частей коммуникации асинхронны (могут происходить в любое время), но некоторые части, которые я хочу быть синхронными (например, ACK для отправленной команды).

Я использую поток, который читает команды из InputStream сокета и вызываетсобытие onCommand ().Сама команда обрабатывается шаблоном Command-Design-Pattern.

Каков наилучший подход (Java), позволяющий ожидать ACK без пропуска других команд, которые могут появляться одновременно?

con.sendPacket(new Packet("ABC"));
// wait for ABC_ACK

edit1

Думайте об этом как о FTP-соединении, но обе команды данных и управляющие команды находятся в одном соединении.Я хочу перехватить ответ на команду управления, когда поток данных в фоновом режиме работает.

edit2

Все отправляется в блоках для включения нескольких (разные) передачи по одному и тому же TCP-соединению (мультиплексирование)

Block:
1 byte - block's type
2 byte - block's payload length
n byte - block's paylod

Ответы [ 2 ]

4 голосов
/ 05 июня 2011

В принципе, вам нужен реестр заблокированных потоков (или, что лучше, блокировок, на которых они ожидают), с ключом с некоторым идентификатором, который будет отправлен удаленной стороной.

Для асинхронной работы вы просто отправили сообщение и продолжили.

Для синхронной работы, после отправки сообщения, ваш отправляющий поток (или поток, который инициировал это) создает объект блокировки, добавляет его с некоторым ключом в реестр и затем ожидает блокировки до получения уведомления.

Поток чтения, когда он получает какой-либо ответ, ищет в реестре объект блокировки, добавляет к нему ответ и вызывает notify(). Затем идет чтение следующего ввода.

Тяжелой работой здесь является правильная синхронизация, чтобы избежать мертвых блокировок, а также пропустить уведомление (потому что оно возвращается до того, как мы добавили себя в реестр).

Я сделал что-то подобное, когда реализовал протокол удаленного вызова метода для нашего Fencing -аплета. В принципе RMI работает так же, только без асинхронных сообщений.

1 голос
/ 05 июня 2011

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

Скажем, у вас нет фонового потока, считывающего результаты в соединении.Вместо этого вы можете использовать текущий поток для чтения любых результатов.

// Asynchronous call
conn.sendMessage("Async-request");
// server sends no reply.

// Synchronous call.
conn.sendMessage("Sync-request");
String reply = conn.readMessage();
...