Модераторы: javastic, AntonSaburov

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Прием данных отдельно через сокет, сообщение, затем файл 
:(
    Опции темы
YuraDoc
Дата 5.5.2008, 12:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 140
Регистрация: 1.4.2006
Где: Zhytomir, Ukraine

Репутация: нет
Всего: нет



У меня есть сокетное соединение между компьютером и мобильным телефоном.
Создан некий протокол обмена сообщениями.

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

Заранее благодарен за ответ.
PM MAIL WWW ICQ Skype   Вверх
eugine_s
Дата 5.5.2008, 12:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 581
Регистрация: 14.11.2007
Где: Киев

Репутация: 17
Всего: 17



Сообщение - это хоть и строка, но передается тоже в качестве набора байт....

Поэтому можно передавать все байтами. 

Код

byte msgData [] = "твоя_строка_с_настройками".getBytes();
byte msgDataSize = msgData.getLenght();
byte imgData [] = //байты изображения.



и отправлять в это на мобильный в таком порядке:
1. один байт равный msgDataSize
2. N байт - строка сообщения (N = msgDataSize);
3. imgData

Мобильный эти байты обрабатывает вот так:
1. Читает первый байт. Получает N.
2. Читает N следующих байт и из них строит строку.
String str = new String(byte data[]);
3. Читает все остальные байты - байты картинки.

Я правильно понял твой вопрос?


PM MAIL   Вверх
YuraDoc
Дата 5.5.2008, 13:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 140
Регистрация: 1.4.2006
Где: Zhytomir, Ukraine

Репутация: нет
Всего: нет



Да ты правильно меня понял.
Но у меня прикол в том что сервер обрабатывает сообщения к которым прикреплен "\n" с помощью BufferedReader. Было бы неплохо реализовать нечто подобное и на мобильнике. Т. е. обойти передачу размера сообщений и т.д.
PM MAIL WWW ICQ Skype   Вверх
Dummy
Дата 5.5.2008, 14:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 263
Регистрация: 21.5.2007

Репутация: 7
Всего: 19



Самое высокоуровневое для работы с потоками, что есть в CLDC (соответственно, и в MIDP), - это DataInputStream / DataOutputStream, которые позволяют читать / писать строки через readUTF / writeUTF. Тогда для передачи на телефон можно делать примерно следующее:

Код

OutputStream os  = // getOutputStream() от твоего Socket;
DataOutputStream dos = new DataOutputStream(os);
String msg = "твоя_строка_с_настройками";
byte  imgData[] = // байты изображения

dos.writeUTF(msg);
dos.write(imgData, 0, imgData.length);


Соответственно, на стороне телефона читать примерно так:

Код

InputStream is = // openInputStream() от твоего SocketConnection;
DataInputStream dis = new DataInputStream(is);

String receivedMsg = dis.readUTF();

// дальше читаешь байты изображения, например, в ByteArrayOutputStream, пока поток не закончится


Неудобный момент здесь в том, что readUTF / writeUTF должны работать в паре, иначе возможны неудобства с чтением модифицированного UTF, в который преобразуется передаваемая строка.

Это сообщение отредактировал(а) Dummy - 5.5.2008, 14:32
PM MAIL   Вверх
YuraDoc
Дата 5.5.2008, 18:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 140
Регистрация: 1.4.2006
Где: Zhytomir, Ukraine

Репутация: нет
Всего: нет



Спасибо всем. Проблема решена так: сообщение читалось побайтно, находился '\n', затем DataInputStream.readFully(buf) читает файл.

И кстати ничего плохого нет в том что я читаю методом DataInputStream.readFully(buf) файл?
У меня в проге паралельно читаются файлы на мобилу.
А также, реализовано ли параллельное чтение файла в MIDP?

Это сообщение отредактировал(а) YuraDoc - 5.5.2008, 18:52
PM MAIL WWW ICQ Skype   Вверх
Dummy
Дата 5.5.2008, 20:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 263
Регистрация: 21.5.2007

Репутация: 7
Всего: 19



Ну, концептуально в readFully() нет особо плохого ничего, за исключением того, что это блокирующий вызов, а значит, ты подвешиваешь поток исполнения на время, пропорциональное размеру читаемых данных. В твоем случае это может быть весьма значительно. Это означает, что этот метод не стоит вызывать из GUI-callback-функций, таких как Displayable.commandAction, обработчиков типа Canvas.keyPressed, Canvas.keyReleased, Canvas.hideNotify, Canvas.showNotify и другие, вызываемые из контекстов системных потоков, иначе просто подвесишь графическую систему и обработку событий JVM на весь период чтения. Не все JVM умеют умно отдавать управление системе в заданные интервалы. А это значит, что JVM просто может не отдать управление ОС до тех пор, пока не закончит чтение, даже в том случае, если ты пустишь чтение данных в отдельном потоке.

Кроме того, ты же, вроде, сам говорил, что не хочешь возиться с передачей длин сообщений. А с использованием readFully это неизбежно, т. к. ты должен выделить буфер соответствующего размера и подать его на вход этой функции, чтобы считать все разом - тебе ведь это нужно?

Если ты выберешь буфер фиксированного размера, то, возможно, придется вызывать readFully() несколько раз, чтобы считать все данные без остатка. Но в таком случае лучше выбрать обычный read(), который честно считает столько данных, сколько получится, и может вернуть управление, даже если данные в потоке еще есть, а буфер заполнен не целиком. 

Лично мне не совсем ясно, что такое "параллельное чтение файла". Чтение данных от разных файлов из нескольких сокетов? Так это пожалуйста, ограничение здесь, в основном, исходит от платформы - на количество одновременно открытых сокетов, например. Читать из одного потока данных несколькими тредами? Тогда непонятно, какой в этом смысл.
PM MAIL   Вверх
Majesty
Дата 6.5.2008, 08:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 98
Регистрация: 20.3.2005
Где: Almaty, Kazakhsta n

Репутация: нет
Всего: нет



Кстати, к вопросу о блокирующих вызовах smile
Не мог ли бы кто-нибудь привести пример правильного пользования такими вызовами?
Я пишу одно приложение, работающее с камерой и, соответственно, использующее такой вызов.
Как ни пытался, а отделить его от гуя у меня мозгов не хватает.
То есть, я выкидываю капчу с камеры в отдельный поток, но вызывать-то её всё равно приходится из commandAction'а smile 
Телефон (SE K700) с этим нормально справляется, а вот WTK'шный эмулятор безнадёжно виснет.
PM MAIL WWW   Вверх
YuraDoc
Дата 6.5.2008, 11:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 140
Регистрация: 1.4.2006
Где: Zhytomir, Ukraine

Репутация: нет
Всего: нет



readFully() я вызываю в отдельном потоке. Выходит, что это не помогает я так понял.
Как только я считал этим методом я с помощью паттерна Observer уведомляю GUI о том, что пришли данные.
Цитата

Кроме того, ты же, вроде, сам говорил, что не хочешь возиться с передачей длин сообщений. А с использованием readFully это неизбежно, т. к. ты должен выделить буфер соответствующего размера и подать его на вход этой функции, чтобы считать все разом - тебе ведь это нужно?

Размер данных на входе я узнаю с помощью метода in.available() (или это не верно?).

"параллельное чтение файла" - под этим я имел ввиду, когда несколько сокетов читает и передает один файл. Работает ли это в большинстве случаев?
PM MAIL WWW ICQ Skype   Вверх
Dummy
Дата 6.5.2008, 13:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 263
Регистрация: 21.5.2007

Репутация: 7
Всего: 19



Цитата

Размер данных на входе я узнаю с помощью метода in.available() (или это не верно?).


Использовать InputStream.available() для выяснения размера передаваемых данных не стоит. При потоковой передаче данных фишка как раз в том, что размер итоговых данных в общем случае неизвестен. По спецификации MIDP этот метод возвращает количество байт, которые на момент вызова можно считать из потока без блокировки, т. е. это некоторый объем кэшированных данных. Например, если ты используешь какой-нибудь буферизованный поток, читающий из сети, то он просто может считывать данные с упреждением, но это не означает, что в кэш будут считаны все данные разом.

Для каких-то типов потоков (например, поток из файла) available теоретически может вернуть полный размер данных (опять же зависит от реализации), но далеко не всегда.

Цитата

readFully() я вызываю в отдельном потоке. Выходит, что это не помогает я так понял.


Я не хочу сказать, что это не помогает. Просто придерживаюсь мнения, что в твоей ситуации применение readFully() не оправдано.

Добавлено через 5 минут и 54 секунды
Majesty,

Цитата

То есть, я выкидываю капчу с камеры в отдельный поток, но вызывать-то её всё равно приходится из commandAction'а
Телефон (SE K700) с этим нормально справляется, а вот WTK'шный эмулятор безнадёжно виснет. 


Можешь привести пример кода для твоей ситуации? У меня подозрения есть, с чем это может быть связано.

Это сообщение отредактировал(а) Dummy - 6.5.2008, 13:24
PM MAIL   Вверх
YuraDoc
Дата 6.5.2008, 14:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 140
Регистрация: 1.4.2006
Где: Zhytomir, Ukraine

Репутация: нет
Всего: нет



Неужеле никто не знает, можно ли обращатся к файлу на мобиле одновременно, с разных сокетов, в разных потоках?
PM MAIL WWW ICQ Skype   Вверх
Dummy
Дата 6.5.2008, 14:56 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 263
Регистрация: 21.5.2007

Репутация: 7
Всего: 19



Цитата

Неужеле никто не знает, можно ли обращатся к файлу на мобиле одновременно, с разных сокетов, в разных потоках? 


Я не думаю, что кто-то здесь тебе даст универсальный ответ. Если реализация JSR-75 разрешает тебе открыть несколько потоков чтения из одного файла, то ради Бога. Если нет - получишь IOException на попытке открыть второй поток из файла. Все зависит от платформы и от реализации JVM - можно ли на ней несколько раз открыть файл в режиме чтения. Посмотри, как ведет себя WTK в такой ситуации. Потом возьми реальные железки и пробуй. В любом случае твой код должен правильно обрабатывать ситуацию, когда можно открыть не более одного потока из файла.


Это сообщение отредактировал(а) Dummy - 6.5.2008, 14:58
PM MAIL   Вверх
DarK__AngeL
Дата 12.5.2008, 12:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 43
Регистрация: 7.12.2007

Репутация: нет
Всего: нет



Цитата(YuraDoc @ 6.5.2008,  14:36)
Неужеле никто не знает, можно ли обращатся к файлу на мобиле одновременно, с разных сокетов, в разных потоках?

проще завести перменную:
Код

InputStream file

а потом уже её использовать для всех потоков

Добавлено через 1 минуту и 51 секунду
у меня же такой вопрос на эту тему: как вообще сохранить файл, который приходит в байтовом массиве? то есть как узнать расширение, да и вообще, как происходит сохранение файлов в J2ME?
PM MAIL   Вверх
Dummy
Дата 12.5.2008, 14:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 263
Регистрация: 21.5.2007

Репутация: 7
Всего: 19



Цитата

проще завести перменную: InputStream file

а потом уже её использовать для всех потоков


Такой подход требует:
  • Четкой синхронизации доступа потоков выполнения к потоку данных
  • Постоянного использования mark() и reset() для общего потока данных, т. к. потоки по определению "почти" необратимы. А это возможно, только если данный экземпляр InputStream поддерживает такую функциональность, что само по себе не факт (по умолчанию InputStream.mark() не делает ничего, а reset() выкидывает IOException).
Аналогичного результата можно намного проще добиться, считывая данные из сокета в некий массив-буфер, а затем уже несколькими потоками считывать из буфера данные, в этом случае каждый поток должен будет поддерживать маркер позиции, откуда ему следует читать данные. Ну, остальные детали - дело техники.

Цитата

как вообще сохранить файл, который приходит в байтовом массиве

как происходит сохранение файлов в J2ME


Либо в RMS, либо, если в телефоне есть поддержка JSR-75, прямо-таки в файл. Об этом на форуме информации туча. Да и сам JSR-75 - довольно простой для понимания на базовом уровне документ.

Цитата

то есть как узнать расширение


Данные, которые из потока читаются, в строгом смысле "файлом" не являются, а станут им только после того, как будут сохранены в файловой системе телефона. Именно тогда они получат имя и, возможно, расширение. Один вариант - придумать свой протокол при передаче через сокеты - например, передавать имя файла вначале, а затем его данные. Еще вариант - использование OBEX, но TCP/IP OBEX может и не поддерживаться на телефоне.


Это сообщение отредактировал(а) Dummy - 12.5.2008, 15:00
PM MAIL   Вверх
DarK__AngeL
Дата 12.5.2008, 17:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 43
Регистрация: 7.12.2007

Репутация: нет
Всего: нет



насчёт InputStream file: а копировать эту переменную для каждого потока не выход?
PM MAIL   Вверх
Dummy
Дата 12.5.2008, 22:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 263
Регистрация: 21.5.2007

Репутация: 7
Всего: 19



Нет, не выход. Реальный поток данных все равно один. Так что если несколько потоков будут читать из него попеременно, то в результате каждый из них просто получит какие-то обрывки данных, причем из разных мест передаваемого файла. 
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса

  • Прежде чем задать вопрос прочтите это!
  • Литература по Java находится здесь.
  • Литературу по Java обсуждаем здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит" (возле кнопок кодов) если у Вас нет русских шрифтов.
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда

  • FAQ раздела лежит здесь!
 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java ME (J2ME) | Следующая тема »


 




[ Время генерации скрипта: 0.1006 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.