Как правильно получить массив байт по TCP/IP?

256
18 апреля 2017, 07:41

Есть сервер, который по команде присылает некоторое количество байт. Объём данных заранее известен - 280 Кбайт. Данные передаются через Wi-Fi сеть по TCP/IP соединению. Используется собственный протокол, который никак не отображает кол-во передаваемой информации. Вся ̶п̶р̶о̶б̶л̶е̶м̶а̶ особенность сервера в том, что он открывает поток (stream) и передает информацию фреймами разного размера. Размер каждого фрейма может колебаться в пределах от 10 до 2048 байт. Он будет передавать фреймы, пока не передаст весь объем данных (280 Кбайт). Другими словами, при приёме данных на Android-устройстве я никак не могу определить объем получаемых данных в потоке, соответственно, не могу разместить все данные в правильном виде.

Вопрос: Как правильно реализовать приём данных при таких "особенностях"?

Возможное решение: Я решил попробовать создать массив размером 2048 (максимально возможный размер фрейма) байт и записывать каждый новый фрейм в этот массив:

DataInputStream din = new DataInputStream(socket.getInputStream());
byte[] buffer = new byte[2048];
din.read(buffer);

Далее данные из моего buffer массива я пробовал помещать в коллекцию ArrayList, однако здесь возникла другая проблема: как определить, где закончились нужные данные, которые я сохранил в массив buffer?

Answer 1

Так как вы заранее знаете объём передаваемых данных, то имеет смысл создать один большой массив (если полученные данные вам нужны целиком), после чего записывать в него блоками считанные байты.

Определить количество считанных в буфер байтов можно по числу, возвращаемому методом read.

Привязывать сюда списки - лишняя трата памяти и лишние неудобства (придётся ведь ещё для каждого считанного "куска" хранить его реальный размер).

Схематичный код чтения данных блоками и запись в результирующий массив:

public byte[] read(Socket socket) throws IOException
{
    byte[] array = new byte[280 * 1024];
    int arrayPointer = 0;
    DataInputStream din = new DataInputStream(socket.getInputStream());
    byte[] buffer = new byte[2048];
    int readCount;
    while ((readCount = din.read(buffer)) != -1)
    {
        System.arraycopy(buffer, 0, array, arrayPointer, readCount);
        arrayPointer += readCount;
    }
    return array;
}
READ ALSO
Парсинг json в java

Парсинг json в java

Хочу сделать так, чтобы i-тому элементу hostidList соответствовал i-тый host (тип ArrayList)Но проблема в том, что не могу корректно то ли ввести, то ли вывести...

357
Как сравнить String и StringBuffer?

Как сравнить String и StringBuffer?

Нужно определить, является ли введенный текст палиндромомПалиндро́м — буквосочетание, слово или текст, одинаково читающееся в обоих направлениях

275
Кастомные jpa update/delete query

Кастомные jpa update/delete query

Откуда код вызывается:

326
Путь к картинкам в JAR файле

Путь к картинкам в JAR файле

Собрал проект мавеном в JAR файлВнутри архива есть папка с картинками, однако не могу понять, как прописать путь к этим файлам так, чтобы можно...

331