Массив не успевает обработаться

225
06 июля 2017, 01:10

Добрый день. Есть следующая проблема, сервер присылает на устройство данные размером 5125 байт. Обмен идёт по tcp/ip протоколу. Сервер сделан таким образом, что он присылает все данные фреймами, максимальный размер которых равен 2000. Таким образом размер фрейма колеблится от 5 байт до 2000 байт. Как я получаю данные:

   synchronized void receiveData(){
    int readCount;
       try {
            byte[] buffer = new byte[2048];
            while (din != null && (readCount = din.read(buffer)) != -1) {
            checkIncomeMsg(buffer, readCount);
            }
       }
    }
catch (IOException e){
 Log.i("LOG_TAG", "Вылетел Exception в ReceiveService");
}
}

Массив, счетчик и константа:

private static final int SHUT_DOWN_HISTORY_SIZE = 5125;
private static int shut_down_pointer = 0;
byte shutdown_history_array = new byte[5125];

checkIncomeMsg:

synchronized void checkIncomeMsg(byte[] data, int count_byte) {
        Log.i(MY_TAG, "размер входящего массива - " + count_byte);
 System.arraycopy(data, 0, shutdown_history_array, shut_down_pointer, count_byte);
 shut_down_pointer += count_byte;
  if (shut_down_pointer == SHUT_DOWN_HISTORY_SIZE){
     Log.e("LOG_TAG", "Получили весь объём данных");
  }
}

Так вот, вся проблема в том, что на одних устройствах весь объем данных я успешно получаю, а на других устройствах происходит ситуация, как будто приходит новый фрейм, а данные со старого фрейма еще не успели сохранится в методе checkIncomeMsg и он вызывается заново, таким образом я теряю часть данных.

Вопрос: Подскажите как решить данную проблему или посоветуйте куда копать.

Возможное решение: может стоит сделать какую-то очередь?

Answer 1

Таааак. Возможно, вам поможет такой метод класса DataInputStream, как readFully(byte[] buffer). Он считывает байты из входного потока и записывает их в буфер buffer. Он блокирует выполнение программы пока не произойдет одно из следующих событий:

  • buffer.length байт входных данных вычитаны
  • обнаружен конец файла
  • при возникновении какой-либо ошибки ввода / вывода.

соответственно ваш код будет выглядеть так:

public byte[] receiveData()
{
   try {
       byte[] buffer = new byte[SHUT_DOWN_HISTORY_SIZE];
       din.readFully(buffer);
       return buffer;
   }catch (IOException e){
       Log.i("LOG_TAG", "Вылетел Exception в ReceiveService");
       return null;
   }
}
READ ALSO
Как сделать связку commitEdit() и getValue()?

Как сделать связку commitEdit() и getValue()?

Как мне реализовать вызов commitEdit в данном случае, чтобы получать getValue из форматтера? Читаю документацию https://docsoracle

225
Как включить wsdl файл в package my.some.package при сборке jar в gradle?

Как включить wsdl файл в package my.some.package при сборке jar в gradle?

При компиляции jar'ок средствами Ant в них, по дефолтным настройкам, включаются и допфайлы который нужны для проекта, т

303
Исключения в intent.putExtra

Исключения в intent.putExtra

Вопрос к более опытным программистам, передаю значения через intentputExtra, это же все помещается в try-catch, так вот там много setText(intent

268