асинхронное закрытие канала сокета

#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() не имеет ничего общего с буферизованными данными, которые в первую очередь подтверждаются получателем.