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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как читать байты из сокета 
V
    Опции темы
uranpro
Дата 29.7.2010, 12:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 571
Регистрация: 7.5.2008
Где: Moscow city

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



Доброго времени суток.

Пишу приложение для своего телефона, нужно отправить\принять, допустим, ~2000 байт.
BUFFER_SIZE = 1024;
Я столкнулся с такими проблемами, когда начал тестить на реальном телефоне(хотя на эмуляторе все работало):
1. не читает из потока
Код

inputStream.read(buffer);

2. после решения 1 проблемы, не читает до конца, т.е. первый раз считал 1024, а оставшиеся 976 не хочет.

Лазил по форумам, ничего не нашел.

Решение
1. перед чтением проверяем, есть ли байты для чтения
Код

    private int getAvelible() throws IOException{
        int av = 0;
        while ((av = inputStream.available()) == 0){
            try {
                Thread.sleep(100);
            } catch (InterruptedException ex) {
                addResult("RTC", "SleepEx: " + ex.getMessage());
            }
        }
        return av;
    }

2. если данных для чтения осталось меньше BUFFER_SIZE, то используем перегруженный метод read
Код

        int totalReceived = 0;
        int toRecv = 0;
        while (totalReceived < length){
            av = getAvelible();

            toRecv = length - totalReceived;

            if (toRecv < BUFFER_SIZE)
                recv = inputStream.read(buffer, 0, toRecv);
            else
                recv = inputStream.read(buffer);

            if (recv != -1)
                System.arraycopy(buffer, 0, data, totalReceived, recv);
            else
                throw new IOException("Received -1");

            totalReceived += recv;
        }


может кому понадобится =)


--------------------
I want a perfect soul
PM MAIL ICQ   Вверх
eugine_s
Дата 29.7.2010, 13:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Вот тут дан ответ почему у тебя могут быть ошибки при работе (проблема 1). 
Процитирую: 
Цитата(Dancer @  1.12.2009,  13:31 Найти цитируемый пост)
  size = is.available(); - это может вернуть 0, но это не будет означать, что мы всё уже приняли. Нельзя по этой вещи организовывать цикл.
лучше смотреть на количество прочитанных байт
  i  = is.read(im, 0, size); - как i у нас станет "-1", это и будет означать, что более уже читать нечего, и можно закругляться.
А когда is.avaliable() возвращает 0, то можно вычитывать по 1 байту, пока не будет достаточно байт, для того чтобы считать их пачкой в массив.


Решение проблемы 1 скорее всего будет решением проблемы 2.

Добавлено через 7 минут и 4 секунды
Вот что в доке по InputStream.available() сказано: 
Цитата

Returns the number of bytes that can be read (or skipped over) from this input stream without blocking by the next caller of a method for this input stream. The next caller might be the same thread or another thread.
The available method for class InputStream always returns 0.

This method should be overridden by subclasses.



1) InputStream.available() всегда возвращает 0. 
2) available() "should be overridden" что переводится как "не плохо было бы если бы наследники InputStream переопределили этот метод", но это не значит, что метод 100% переопределен в наследнике. 

Это сообщение отредактировал(а) eugine_s - 29.7.2010, 13:11
PM MAIL   Вверх
uranpro
Дата 29.7.2010, 13:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 571
Регистрация: 7.5.2008
Где: Moscow city

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



спасибо!

посему в доках по InputStream.read(b) написано
Код

This method blocks until input data is available

???


--------------------
I want a perfect soul
PM MAIL ICQ   Вверх
eugine_s
Дата 29.7.2010, 16:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Часть данных еще может быть не получена. 

Например, ты подключился к серверу, он тебе в ответ начинает слать какие-то данные. Шлет он их пачками/блоками (например, по 1024). 

Телефон может получить уже часть (блок) байт и ожидает прихода следующей части, а ты в это время вызываешь read(). Что тебе должна JVM в этом случает вернуть? "-1" - это не правильно, ведь еще не все данные пришли. сразу выбросить exception - тоже не правильно (exception только через некоторое время выбрасывается - по прохождению какого-то времени). Поэтому твой вызов блокируется, пока не поступят данные. 

Метод available() и "This method blocks until input data is available" - это про разные available идет речь. 
PM MAIL   Вверх
uranpro
Дата 29.7.2010, 22:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 571
Регистрация: 7.5.2008
Где: Moscow city

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



это TCP, -1 выдаст при отключении, Exception при разрыве. если бы я хотел такой геморрой, то использовал бы UDP) avalible тут не причем, я про read "блокирует поток до тех пор, пока данные не становятся доступными". было бы замечательно, если бы выкидывал Exception, тем самым намекая в чем проблема... благо, что пакеты приходят поочередно)))

Это сообщение отредактировал(а) uranpro - 30.7.2010, 10:22


--------------------
I want a perfect soul
PM MAIL ICQ   Вверх
eugine_s
Дата 30.7.2010, 10:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Ну расскажи тогда, как ты делаешь в C#, когда начал читать из сокета (т.е. сокет сказал что готов к чтению), прочитал, грубо говоря, половину данных,  а остальные данные еще не пришли? Усыпляешь поток или забиваешь на остальные данные?

Цитата(uranpro @  29.7.2010,  22:50 Найти цитируемый пост)
кстати, яву недели две изучаю, такие мелочи убивают... 

Зачем вообще с j2me связался smile ? Смотрел бы в сторону обычной java. 

Это сообщение отредактировал(а) eugine_s - 30.7.2010, 10:44
PM MAIL   Вверх
uranpro
Дата 30.7.2010, 12:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 571
Регистрация: 7.5.2008
Где: Moscow city

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



)) ну с j2me связался из-за моего телефона Nokia 6233 )))
хочу написать для себя клиент удаленного торрента.
пока едешь/идешь(в метро) домой, поставил на скачку фильм и готово, ждать не нужно и, если забудешь, вспоминать не надо...

про C# я немного загнул, это обработка API WinSock
WinSock errors
обработка  WSAEWOULDBLOCK
Код

        void CustomSend(Socket socket, byte[] buffer, int length)
        {
            try
            {
                socket.Send(buffer, length, SocketFlags.None);
            }
            catch (SocketException ex)
            {
                if (ex.ErrorCode == 10035)
                {
                    Thread.Sleep(100);
                    CustomSend(socket, buffer, length);
                }
                else
                    throw ex;
            }
        }

Асинхронное чтение
Код

void ReceiverCallBack(IAsyncResult iar)
        {
            ConnectionInfo connectionInfo = (ConnectionInfo)iar.AsyncState;
            try
            {
                int recv = connectionInfo.Client.EndReceive(iar);
                if (recv > 0)
                {
                    //

                    _OnResult(string.Format("Server received {1} bytes from client '{0}'", connectionInfo.Client.RemoteEndPoint, recv));
                    
                    _OnDataReceived(connectionInfo.Client, connectionInfo.Buffer, recv);

                    connectionInfo.Client.BeginReceive(connectionInfo.Buffer,
                        0,
                        connectionInfo.Buffer.Length,
                        SocketFlags.None,
                        new AsyncCallback(ReceiverCallBack),
                        connectionInfo);

                }
                else
                    CloseConnection(connectionInfo);
            }
            catch (SocketException ex)
            {
                _OnResult(string.Format("Receiver SException: '{0}', EC: {1}", ex.Message, ex.ErrorCode));
                CloseConnection(connectionInfo);
            }
            catch (Exception ex)
            {
                _OnResult(string.Format("Receiver Exception: '{0}'", ex.Message));
                CloseConnection(connectionInfo);
            }
        }

этот код залочит поток, если нет данных, -1 если сокет отключился(-или)
Код

int recv = connectionInfo.Client.Receive(b);



--------------------
I want a perfect soul
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса

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

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


 




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


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

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