#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
Необходимы для работы с объектами, размер которых превышает первоначально выделенный буфер фиксированного размера.