Считывание сокета Java заблокировано / не удалось, исключений не было, был задан параметр сети (TCP / IP) - PullRequest
0 голосов
/ 12 ноября 2010

Мы недавно видели эту ошибку. Сервер отправил ответное сообщение (MSG1) одному из своих клиентов (размер сообщения> 64 КБ). Что-то случилось при чтении клиента, это сообщение не было получено вообще. Ни исключение SocketTimeOutException, ни IOException не были выброшены. Сервер попытался отправить другое сообщение (MSG2), но заблокировал его запись (буферы на уровне TCP / IP могли быть заполнены MSG1). Прошло 2 часа, прежде чем мы поняли это и пришлось перезапустить все. Нам удалось смоделировать то же самое, замедлив чтение клиента (сделав паузу на 2 с) и заставив сервер отправлять похожие сообщения (размер> 64 КБ) как обычно.

Во-первых, мы не видели причин, по которым клиент мог бы читать медленно, в течение многих месяцев он мог справиться с такими сообщениями без проблем. Я хотел бы знать (а), что вызывает такого рода тупик, если клиент прочитал

getInputStream().read(byBuf)
медленнее, чем запись на сервере
getOutputStream().write(MSG1)
(byBuf - это байтовый буфер размером 512 байт) (b) Может ли ошибка сокета или н / ж вызвать такую ​​блокировку в противном случае?

Мы используем JDK 1.6.0.

Большое спасибо!

Ответы [ 2 ]

0 голосов
/ 14 ноября 2010

Похоже, проблема сети - возможно, перегруженная связь или сломанный межсетевой экран между двумя хостами. «Воспроизведение» проблемы путем добавления задержек к клиенту не скажет вам ничего интересного, только то, что буферизация на уровне ОС работает так, как задумано:)

Вам необходимо выяснить, почему пакеты задерживаются, что обычно означает tcpdump / wireshark на обоих концах. Если проблема возникает только каждые несколько месяцев, тогда это, вероятно, излишне - сфокусируйтесь на улучшении того, как приложение обрабатывает этот сценарий и / или как вы обнаруживаете, повторяется ли оно.

Кроме того, Java не позволяет устанавливать тайм-аут записи, поэтому для восстановления из этого сценария reader должен вызвать setSoTimeout перед чтением, а затем закрыть сокет, если при чтении выбрасывается SocketTimeoutException. В этом случае запись должна завершиться с ошибкой SocketException («сброс соединения по одноранговому узлу»), хотя это может занять некоторое время, если соединение медленное / прерывистое.

0 голосов
/ 14 ноября 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...