Отправка объектов через неблокирующие сокеты Java NIO

#java #sockets #serialization #nio

#java #сокеты #сериализация #nio

Вопрос:

Я получаю исключение при попытке использовать:

 oos = new ObjectOutputStream(socketChannel.socket().getOutputStream());
oos.writeObject(o);
  

И это вызывает исключение:

 java.nio.channels.IllegalBlockingModeException
  

Невозможно ли передавать объекты в неблокирующие сокеты?
Если это так, как мне следует продолжить передачу объектов сообщений по каналам сокетов?

Я искал этот ответ в других местах, но не смог его найти…

Ответ №1:

Вероятно, вы захотите написать свою собственную ObjectOutputStream реализацию, которая создает a ByteBuffer и write() передает ее каналу.

При использовании неблокирующих сокетов вы не можете напрямую использовать сокет канала; вам необходимо использовать методы канала read() и write() .

Когда вы пишете свои собственные ObjectOutputStream , вам в основном нужно переопределить write() методы для буферизации выходных данных и использовать flush() метод для записи буфера в канал. Затем переопределите writeObject() метод, чтобы он выглядел следующим образом:

 public void writeObject(Object o) throws IOException {
    super.writeObject(o);
    flush();
}
  

чтобы убедиться, что данные записываются после каждой записи объекта.

Комментарии:

1. Итак, в принципе, я бы создал свой собственный выходной поток и просто изменил его на запись с помощью ByteBuffer вместо byte[], но я не понимаю, как я собираюсь использовать этот выходной поток, если я не могу получить поток сокета. Извините, но я никогда не использовал этот вид связи более низкого уровня в java. Пример был бы потрясающим.

2. Извините, если я не совсем ясно выразился. Я имел в виду, что этот новый выходной поток обернет канал, используя write() метод канала, а не write() метод сокета канала.

Ответ №2:

Прошло некоторое время с тех пор, как я работал в этой области, но это казалось более сложным, чем просто перенос writeObject . java.nio обычно ожидаются буферы фиксированного размера (хотя, я полагаю, вы можете динамически их распределять), и ваши удаленные конечные точки должны знать, сколько читать для произвольного Object поступления по проводу. В итоге я отправил начальный int заголовок, сообщающий другому концу, какой объем данных следует ожидать, а затем сериализовал объект в массив байтов и отправил его по проводам.

У меня есть такой пример, в котором все еще могут быть некоторые ошибки, поэтому используйте на свой страх и риск. PendingDataBufferS Необходимы для работы с объектами, размер которых превышает первоначально выделенный буфер фиксированного размера.