TCP Socket зависает при получении в Java - PullRequest
2 голосов
/ 29 октября 2010

Я использую сокет TCP в своем приложении Java.Я пытаюсь получить байтовые данные с какого-либо устройства методом readInt().

Этот метод работает нормально, если я получаю 4 байта от устройства.Но если я получаю меньше 4 байтов или ничего, то readInt() зависает.Он заблокирован и не возвращается.Должно выдаться исключение EOFException, если нет данных для приема, но оно зависает.

Код:

DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
DataInputStream   din = new DataInputStream(socket.getInputStream());

int res = din.readInt();

Ответы [ 4 ]

4 голосов
/ 29 октября 2010

EOFException не выдается, пока сокет не закроется.

Этот метод должен блокироваться при попытке прочитать больше данных, чем доступно. Он возвращает EOFException только тогда, когда сокет закрывается, так как это фактическое условие EOF. Если сокет остается открытым, он блокируется, пока не будет достаточно данных для выполнения запроса.

Это часть фундаментальной природы работы сокетов. Чтобы Java вел себя по-другому, ему пришлось бы неправильно реализовывать поведение сокета.

При составлении протокола сокета вы должны учитывать это. Почему вы ждете получения int, и отправляется только часть int? Этого никогда не должно случиться. Если вы хотите отправлять различные типы данных, вы должны сначала включить какой-нибудь байт заголовка, чтобы сообщить получателю, какие данные будут поступать дальше, чтобы он знал, как их обрабатывать и что с ними делать.

1 голос
/ 29 октября 2010

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

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

Такая ситуация может возникнуть, только если вы неправильно внедрили протокол приложения. Почему вы ожидаете 4-байтовое целое число, а приложение отправляет только 1-3 байта? Это действительно отправка двоичного Int? или, может быть, вы читаете и анализируете строку ASCII?

0 голосов
/ 29 октября 2010

Используемые вами классы являются частью пакета java.io, который выполняет блокировку ввода / вывода.Правильное решение - перейти к использованию неблокирующих классов ввода / вывода, определенных в java.nio.Имейте в виду, что написание неблокирующего приложения ввода-вывода нетривиально.Однако это единственное решение, позволяющее избежать потенциальной блокировки потока ввода-вывода на неопределенный срок.

Обратите внимание, что в качестве хакерского решения вы можете использовать выделенный поток блокировки ввода-вывода, который просто читает и добавляет байты в BlockingQueue опрашивается другим потоком.Поток потребителя может вызвать poll(long, TimeUnit) на BlockingQueue с достаточно длительным значением времени ожидания, и если вызов вернул null, это может означать, что больше нет данных.Обратите внимание, что это довольно уродливое решение, так как оно означает, что ваш поток «ввода» ввода / вывода в этот момент останется заблокированным.

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