#java #sockets #bufferedreader #java-io
#java #сокеты #bufferedreader #java-io
Вопрос:
Я использую BufferedReader.readLine()
метод для чтения ответа с удаленного сервера (который написан на C, и у меня нет доступа к исходному коду).
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line;
while((line = br.readLine())!=null){
[...]
}
Но он всегда блокируется в последней строке, пока не истечет время ожидания. Итак, я использовал следующий код:
int b;
while(true){
b = in.read;
[...]
}
и я обнаружил, что последний прочитанный байт имеет целое значение 13, которое, я думаю, является возвратом каретки, верно?
Итак, почему readLine
метод блокируется? Как сервер обычно сигнализирует о достижении конца потока? Спасибо.
Комментарии:
1. Не могли бы вы, пожалуйста, вставить свой неблокирующий код, который вы используете. Я хочу посмотреть, что можно сделать для неблокирующих входных данных
2. @PrakharAgrawal О чем ты говоришь? Здесь нет неблокирующего кода, присутствующего или упомянутого.
Ответ №1:
В случае сетевого подключения поток завершается, когда сокет закрыт.
Поэтому совершенно нормально, что readLine()
блокируется до тех пор, пока не будет получен «конец строки» или вы не закроете соединение вручную. Когда ваш readLine()
получает последний символ со значением ’13’, строка считывается, и цикл начинается снова, ожидая следующей строки.
Нет никакой разницы между «последней строкой» и другими строками.
Для того, чтобы остановить цикл, вы должны вручную закрыть соединение где-нибудь или дождаться истечения времени ожидания. Но без дополнительной информации о вашем протоколе связи невозможно быть более точным в этом.
Комментарии:
1. Вы правы; код ожидает r, а затем запоминает пропустить перевод следующей строки (если таковой имеется).
Ответ №2:
Это зависит от протокола. Если сервер не закрывает поток, readLine будет блокироваться до тех пор, пока не будет получен правильный конец строки. Итак, если сервер никогда не отправляет правильный конец строки, вы заблокированы. Возможно, вам следует использовать более низкоуровневые методы и попытаться получить документацию по протоколу или перепроектировать ее.
Ответ №3:
убедитесь, что в коде сервера есть out.println() вместо out.print()
Ответ №4:
Вы можете расширить условие while, если не используете пустые строки :
while((line = br.readLine())!=null amp;amp; line.length() > 0) {
// ...
}
Комментарии:
1. да, правильная идея. Еще одна вещь, которую вы можете сделать, это использовать специальную последовательность символов в конце сообщения. Объявляя что-то вроде ‘EOM’ = n n где ‘EOM’ — это EndOfMessage
2. За исключением того, что readLine будет блокироваться до тех пор, пока не будет обнаружен конец строки или поток не будет закрыт.