Подтвердить что ты не робот

Java socket/output stream пишет: блокируют ли они?

Если я только ПИСЬМО для сокета в потоке вывода, будет ли он когда-либо блокироваться? Только чтение может блокироваться, не так ли? Кто-то сказал, что записи могут блокироваться, но я вижу только функцию тайм-аута для метода чтения сокета - Socket.setSoTimeout().

Мне не кажется, что запись может блокироваться.

4b9b3361

Ответ 1

Запись на Socket также может блокироваться, особенно если это TCP Socket. ОС будет буферизовать только определенное количество неперехваченных (или переданных, но не подтвержденных) данных. Если вы пишете материал быстрее, чем удаленное приложение может его прочитать, сокет будет в конечном итоге резервным, а ваши вызовы write будут блокироваться.

Отвечая на следующие вопросы:

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

Нет механизма для установки времени ожидания записи на java.net.Socket. Существует метод Socket.setSoTimeout(), но он влияет на вызовы accept() и read() вызовов... и не write(). По-видимому, вы можете получить таймауты записи, если используете NIO, неблокирующий режим и селектор, но это не так полезно, как вы могли себе представить.

Правильно реализованный стек TCP не отбрасывает буферизованные данные, если соединение не закрыто. Однако, когда вы получаете тайм-аут записи, неясно, были ли данные, которые в настоящее время находятся в буферах уровня OS, были получены другим концом... или нет. Другая проблема заключается в том, что вы не знаете, сколько данных из вашего последнего write было фактически перенесено на буферы TCP стека уровня OS. Отсутствует какой-либо протокол уровня приложения для повторной синхронизации потока * единственная безопасная вещь, которую нужно сделать после таймаута на write, - это закрыть соединение.

В отличие от этого, если вы используете сокет UDP, вызовы write() не будут блокироваться в течение какого-либо значительного периода времени. Но недостатком является то, что если есть проблемы с сетью или удаленное приложение не поддерживает, сообщения будут отбрасываться на пол без уведомления об этом. Кроме того, вы можете обнаружить, что сообщения иногда доставляются в удаленное приложение не по порядку. Это будет решать вам (разработчику) решение этих проблем.

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