Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / Считывание информации из сокета / 19 сообщений из 19, страница 1 из 1
19.09.2013, 14:02:21
    #38401496
else12
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Считывание информации из сокета
Считываю информацию из сокета.

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
                        is = socket.getInputStream();
                        os = socket.getOutputStream();
....
                         in = new BufferedReader(new InputStreamReader(is)); 
                         out = new PrintWriter(new OutputStreamWriter(os)); 
....
                              Boolean bReady = in.ready();

                              while (bReady)
                              {
                                    String line = in.readLine();
                                    bReady = in.ready();
...


Так вот in.ready(); в некоторых случаях работает нормально - когда true, то считывает информацию, когда false, то не считывает, а в некоторых показывает, что "тру", но зависает на in.readLine();

А почему так? И как правильно сделать, чтобы не подвиснуть на readLine, а пройти дальше?
...
Рейтинг: 0 / 0
19.09.2013, 14:16:19
    #38401513
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Считывание информации из сокета
readLine() может читать больше данных, чем доступно в буфере или в inputStream без блокирования.
Либо не использовать readLine(). Либо изучать NIO.
...
Рейтинг: 0 / 0
19.09.2013, 14:26:19
    #38401528
else12
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Считывание информации из сокета
BlazkowiczreadLine() может читать больше данных, чем доступно в буфере или в inputStream без блокирования.
Либо не использовать readLine(). Либо изучать NIO.
Я не понял как лучше сделать, если без NIO. Мне шлют информацию, я должен ее считать, а далее проверять, есть ли там информация, и, если нет, то проходить дальше и делать нужные мне действия - и так в цикле.
...
Рейтинг: 0 / 0
19.09.2013, 14:27:48
    #38401532
else12
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Считывание информации из сокета
Собственно, если бы не было зависания - то все бы верно работало, без проблем. Но как его избежать?
...
Рейтинг: 0 / 0
19.09.2013, 14:43:58
    #38401561
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Считывание информации из сокета
else12Я не понял как лучше сделать, если без NIO.

Задавай конкретные вопросы. Что не понятно?

else12Мне шлют информацию, я должен ее считать, а далее проверять, есть ли там информация, и, если нет, то проходить дальше
Смотри. Сначала "считать", а потом "проверять, если есть". Странная постановка задачи. Может наоборот? Многое ещё зависит и от протокола передачи данных...

else12и делать нужные мне действия - и так в цикле.
ОК.

Давай попробую разжевать.
Итак. Данные по сети приходят не все сразу, а по частям. Если данные пришли, их можно читать. Если данные читать, но они не пришли, то потом блокируется до прихода данных.
Это понятно?

Данные, которые пришли, но ещё не прочитаны, могут находится в буфере. Буферов здесь несколько. Один в BufferedReader. Другие, возможны, в реализации работы с Socket на уровне JVM, ОС, железа.
Метод ready() проверяет буфер в BufferedReader и метод InputStream.available(). Последний сигнализирует о наличии данных в скрытых буферах.
Метод readLine() читает все данные до переноса строки (\n).
Почему метод readLine() зависает? Потому что сервер прислал какие-то данные после переноса строки. Но не прислал сам перенос строки. Поэтому readLine() вызывает read(). Который блокирут поток, пока сервер чего-то не пришлет.

Правильное решение зависит от того какой протокол обмена данными реализуется с сервером.
Что делать, если пришла порция данных, но не пришел "разделитель"?
Если сервер строго заканчивает все сообщения "разделителем", то стоит подебажить и посмотреть что же за данные приехали после "разделителя" и перед зависанием.
...
Рейтинг: 0 / 0
19.09.2013, 15:15:33
    #38401622
else12
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Считывание информации из сокета
BlazkowiczПравильное решение зависит от того какой протокол обмена данными реализуется с сервером.
Что делать, если пришла порция данных, но не пришел "разделитель"?
Если сервер строго заканчивает все сообщения "разделителем", то стоит подебажить и посмотреть что же за данные приехали после "разделителя" и перед зависанием.
У меня сервер-сокет, по протоколу TCP мне приходят данные в виде xml-команд. По идее больше ничего приходить не должно. Я устанавливаю соединение, все проходит нормально. Вначале идет инициализация - в цикле я получаю команды, передаю ответы и т.д. Перед зависанием - из того, что я вижу - в буфер пришли именно данные в виде команд - я их принимаю (все верно - команды xml), посылаю ответ, получаю реакцию на ответ - пока идет диалог, все нормально. Но вот я получил последнюю команду инициализации (все это в цикле), а дальше цикл по идее должен работать так - если данные не пришли (а после инициализационных действий они не приходят какое-то время), пройти дальше, а, если пришли - принять их. Но вместо этого я зависаю на ожидании...
...
Рейтинг: 0 / 0
19.09.2013, 15:18:30
    #38401631
else12
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Считывание информации из сокета
BlazkowiczЕсли сервер строго заканчивает все сообщения "разделителем", то стоит подебажить и посмотреть что же за данные приехали после "разделителя" и перед зависанием.
Вроде бы приходит разделитель, а после него ничего не приходит - все, что я считываю, я и смотрю и вывожу на экран. Но почему-то ready говорит, что в буфере что-то есть, а readLine зависает...
...
Рейтинг: 0 / 0
19.09.2013, 15:28:20
    #38401649
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Считывание информации из сокета
else12У меня сервер-сокет, по протоколу TCP мне приходят данные в виде xml-команд.

Ну, вот и ответ. Кто будет гарантировать что xml заканчивается переносом строки? Не один XML генератор не парится с тем чтобы присылать конец строки после конца документа.


else12Но вместо этого я зависаю на ожидании...
Посмотри в дебаге содержимое буфера в BufferedReader. Он пустой?
...
Рейтинг: 0 / 0
19.09.2013, 15:32:37
    #38401660
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Считывание информации из сокета
else12Но почему-то ready говорит, что в буфере что-то есть, а readLine зависает...
Блин. Ну, я же объяснил уже. В буфере нет конца строки. А readLine() читает всё до конца строки. Буфер не пустой. Можно читать. Поэтому читать надо посимвольно и проверять ready(), а не через readLine(). Либо читать до конца XML, а не через readLine().
В твоём случае readLine() это ещё и офигенный оверхед по памяти. Вычитать String-и построчно. Склеить потом в один XML (тоже String?) И потом это всё добро распарсить? При том что парсеры нормально могут напрямую читать InputStream. Нужно лишь прерывать его по окончании XML.
...
Рейтинг: 0 / 0
19.09.2013, 15:56:21
    #38401700
else12
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Считывание информации из сокета
BlazkowiczВычитать String-и построчно. Склеить потом в один XML (тоже String?) И потом это всё добро распарсить? При том что парсеры нормально могут напрямую читать InputStream. Нужно лишь прерывать его по окончании XML.
Вы имеете в виду, что нужно проверить InputStream.available(), И, если тру, то передать парсеру? А прервать поток - это переоткрыть его или что имеется в виду?
...
Рейтинг: 0 / 0
19.09.2013, 16:00:54
    #38401707
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Считывание информации из сокета
else12Вы имеете в виду, что нужно проверить InputStream.available(),

BufferedReader.ready() проверет как свой буфер, так и InputStream.available(). Об этом я написал выше и об этом же написано в JavaDoc.
Использовать Reader или InputStream это уже решать в зависимости от задачи. Я лишь говорю - не использовать readLine() .


else12И, если тру, то передать парсеру?
Нет. Метод может вернуть false из-за задержки сети. Это не значит что пакет окончен.

else12А прервать поток - это переоткрыть его или что имеется в виду?
Создать свой InputStream, который бы завершался согласно спецификации InputStream, когда в основном InputStream завершается пакет. А как именно завершается пакет, это нужно вам выбрать исходя из протокола обмена данными. Вы для себя решили что пакет заканчивается переносом строки. Но думает ли сервер точно так же?
...
Рейтинг: 0 / 0
19.09.2013, 16:07:18
    #38401722
else12
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Считывание информации из сокета
Blazkowiczelse12Вы имеете в виду, что нужно проверить InputStream.available(),

BufferedReader.ready() проверет как свой буфер, так и InputStream.available(). Об этом я написал выше и об этом же написано в JavaDoc.
Использовать Reader или InputStream это уже решать в зависимости от задачи. Я лишь говорю - не использовать readLine() .


else12И, если тру, то передать парсеру?
Нет. Метод может вернуть false из-за задержки сети. Это не значит что пакет окончен.

else12А прервать поток - это переоткрыть его или что имеется в виду?
Создать свой InputStream, который бы завершался согласно спецификации InputStream, когда в основном InputStream завершается пакет. А как именно завершается пакет, это нужно вам выбрать исходя из протокола обмена данными. Вы для себя решили что пакет заканчивается переносом строки. Но думает ли сервер точно так же?
Что-то я запутался, как мне правильно сделать...

У меня есть сокет-сервер, я делаю accept, потом создаю выходной и входной потоки. Я передаю входной поток парсеру или какой поток? Мне надо проверить, могу ли я передать поток парсеру - как это правильно сделать? После обработки потока - пусть стаксом - что мне надо сделать? От клиента я жду xml-команды или какой-то промежуток времени он может ничего не присылать...
...
Рейтинг: 0 / 0
19.09.2013, 16:57:07
    #38401818
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Считывание информации из сокета
else12Что-то я запутался, как мне правильно сделать...

Для начала нужно разобраться как работает каждый элемент пазла
Socket
Stream
Reader
Parser
И только после этого будет понятно как правильно сделать.
Потому что я предлагаю несколько разных решений.

else12Я передаю входной поток парсеру или какой поток?

Нет. Входной поток может содержать много XML. А парсер может читать только 1 до конца InputStream.

else12Мне надо проверить, могу ли я передать поток парсеру - как это правильно сделать?
Не можешь. Нужно создать свой MyInputStream, который бы чтение делегировал оригинальному InputStream. Но при окончании пакета в оригинальном InputStream изображал бы из себя окончания всего InputStream. А на новый пакет, нужно создавать такой же новый экземпляр MyInputStream.

else12После обработки потока - пусть стаксом - что мне надо сделать?

Я не знаю. Что там говорит ТЗ на этот счет?

else12От клиента я жду xml-команды или какой-то промежуток времени он может ничего не присылать...
Да.
...
Рейтинг: 0 / 0
19.09.2013, 17:18:15
    #38401854
else12
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Считывание информации из сокета
BlazkowiczДля начала нужно разобраться как работает каждый элемент пазла
Socket
Stream
Reader
Parser

Код схематично такой. Или что еще надо?

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
                        sSocket = new ServerSocket(.....);
                        Socket socket = sSocket.accept();
...
                        is = socket.getInputStream();
...
                         in = new BufferedReader(new InputStreamReader(is)); 
....
                         parse(in); 
...
     public void parse(InputStream input) 
     {
         XMLInputFactory inputFactory = XMLInputFactory.newInstance();
	 
         try 
	 {
             XMLStreamReader reader = inputFactory.createXMLStreamReader(input);
             process(reader);
....
     public void process(XMLStreamReader reader) throws XMLStreamException 
     {
         while (reader.hasNext()) 
	 {
....
             int type = reader.next();             
             
             switch (type) 
	     {
                case XMLStreamConstants.START_ELEMENT :  
                case XMLStreamConstants.END_ELEMENT:	 
                case XMLStreamConstants.CHARACTERS : 
....
...
Рейтинг: 0 / 0
20.09.2013, 16:33:44
    #38402997
else12
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Считывание информации из сокета
Blazkowiczelse12Что-то я запутался, как мне правильно сделать...

Для начала нужно разобраться как работает каждый элемент пазла
Socket
Stream
Reader
Parser
И только после этого будет понятно как правильно сделать.
Потому что я предлагаю несколько разных решений.

Я все-таки не врубаюсь как правильно написать код... По порядку - я объявляю сокет, делаю accept и после соединения хочу считывать данные в socket.getInputStream(); Пока все верно?
...
Рейтинг: 0 / 0
20.09.2013, 16:38:16
    #38403009
cdtyjv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Считывание информации из сокета
else12 ,
Все верно. Другое дело, что когда вы работаете с BufferedReader.readLine(), то вы не знаете, сколько он вернет байт, так как вы не знаете, где будет конец строки. Что, есди сейчас в стриме доступно (available) 4 байта, но символа "конец строки" там нет? Тогда у вас BufferedReader заблокируется.
...
Рейтинг: 0 / 0
20.09.2013, 16:46:35
    #38403018
else12
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Считывание информации из сокета
cdtyjv else12 ,
Все верно. Другое дело, что когда вы работаете с BufferedReader.readLine(), то вы не знаете, сколько он вернет байт, так как вы не знаете, где будет конец строки. Что, есди сейчас в стриме доступно (available) 4 байта, но символа "конец строки" там нет? Тогда у вас BufferedReader заблокируется.
Можно как-то этого избежать или зависнуть не напрочь, а с выходом из зависания по тайм-ауту?
...
Рейтинг: 0 / 0
20.09.2013, 16:49:54
    #38403022
cdtyjv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Считывание информации из сокета
else12Можно как-то этого избежать или зависнуть не напрочь, а с выходом из зависания по тайм-ауту?Два варианта:
1) Работать с input stream сокета, и ориентироваться на available(). Но как вы в этом случае будете дожидаться появления информации в сокете - хз.
2) Перейти на NIO, там есть ожидание с таймаутами.
...
Рейтинг: 0 / 0
20.09.2013, 16:57:21
    #38403033
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Считывание информации из сокета
else12Можно как-то этого избежать или зависнуть не напрочь, а с выходом из зависания по тайм-ауту?
Использовать разные потоки. Один только для чтения из сокета.
Второй для обработки XML пакетов и прочей фигни, которая не должна зависать.
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / Считывание информации из сокета / 19 сообщений из 19, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]