#java #asynchronous #nio
#java #асинхронный #nio
Вопрос:
У меня есть однопоточный неблокирующий сервер ввода-вывода сокетов, написанный на Java с использованием nio.
Когда я закончу запись в соединение, я хочу закрыть его.
Означает ли закрытие канала блокировку до тех пор, пока получатель не подтвердит все записи в буфере?
Было бы полезно знать, удалось ли это при асинхронном закрытии или нет, но я мог бы смириться с тем, что любые ошибки при закрытии игнорируются.
Есть ли какой-либо способ настроить это, например, с помощью setSoLinger()
(и какие настройки были бы уместны?)
(Общая дискуссия за пределами Java о Linux и других ОС в этом отношении была бы полезна для)
Ответ №1:
Закрытие в неблокирующем режиме является неблокирующим.
Вы могли бы перевести канал в режим блокировки, установить положительный тайм-аут задержки и закрыть, и это заблокировало бы канал на время тайм-аута задержки, пока опустошается буфер отправки сокета, но, увы, Java не выдает исключение, если истек тайм-аут задержки, поэтому вы не можете знать, все ли данные ушли. Я сообщал об этой ошибке десять или более лет назад, и она вернулась «не будет исправлена» из-за проблем с совместимостью. Если вы можете подождать, пока выйдет Java 7, я полагаю, что в nio2 это исправлено, я, конечно, запросил это, но кто знает, когда это произойдет?
И даже если у вас есть все это, все, что вы знаете, это то, что данные были отправлены. Вы ничего не знаете о том, что оно получено или обработано приложением-получателем. Если вам это нужно, вы должны встроить это в свой прикладной протокол.
Комментарии:
1. большое вам спасибо за подтверждение моего понимания, которое я искал!
Ответ №2:
Я не уверен, что происходит на самом деле, но я знаю, что это close()
включает flush()
(за исключением PrintStream
и PrintWriter
…).
Итак, мой подход заключался бы в добавлении соединений для закрытия в очередь и обработке этой очереди во втором потоке (включая обработку ошибок).
Я понимаю, что ваш сервер однопоточный, но второй поток не стоит так дорого, сложность проблемы невелика, и решение будет легко понять при любом обслуживании.
Комментарии:
1. @Schildmeijer: Реальность всегда побеждает правила.
2. сброс при закрытии кажется знакомым по классическим потокам ввода-вывода; но верно ли это и для каналов?
3. @Will: Либо напишите тест, чтобы выяснить наверняка, либо предположите худшее.
4. Все это не имеет значения. Он говорит о неблокирующем вводе-выводе, что означает java.nio, где нет функции flush(), поэтому тестировать нечего; а функция flush() не имеет ничего общего с буферизованными данными, которые в первую очередь подтверждаются получателем.