Проанализируйте пакет DatagramPacket после преобразования его в массив байтов в Java
Я пытаюсь разобрать пакет данных, который я получу в сокете. Я знаю формат пакета, который я получу, который является пакетом DHCPREQUEST, но я не думаю, что это действительно имеет значение. Для простоты рассмотрим только первые шесть полей:
Первое поле - это "код операции", который равен 1 байту.
Второе поле - это "тип оборудования", который равен 1 байту.
В-третьих, "длина аппаратного адреса", 1 байт.
Четвертый, "хмель", 1 байт.
В-пятых, "идентификатор транзакции xid", 4 байты.
Шестое, "секунды", 2 байта.
После того, как я получаю пакет, Мой подход заключается в том, чтобы преобразовать его в массив байтов.
DatagramPacket request = new DatagramPacket(new byte[1024], 1024);
socket.receive(request);
byte[] buf = request.getData();
В этот момент пакет хранится в массиве байтов
buf в виде последовательности байтов. Поскольку я знаю, какова структура этой последовательности байтов, как я могу ее разобрать? Однобайтовые поля достаточно просты, но как насчет многобайтовых полей? Например, как я могу извлечь байты от 4 до 7 и сохранить их в переменной с именем xid?Я мог бы вручную поставить каждый байт в массиве:
byte[] xid = new byte[4];
xid[0] = buf[4];
xid[1] = buf[5];
xid[2] = buf[6];
xid[3] = buf[7];
Но это просто утомительно и непрактично для полей, длина которых составляет сотни байт. Класс String может анализировать подстроки с заданными смещением и длиной; существует ли подобный метод для байтовых массивов в Java?
Или я каким-то образом усложняю себе жизнь?
4 ответов:
Самый чистый способ сделать что-то подобное, вероятно, использовать метод утилиты
Arrays.copyOfRange.
Оберните массив байтов в ByteArrayOutputStream; оберните поток DataInputStream вокруг этого; затем используйте методы DataInputStream.
То, что вы делаете, это пишете себе некоторые вспомогательные методы для извлечения значений 2 байта, 4 байта и т. д. Из пакета, считывая байты и собирая их в Java
short,intили какие бы то ни было ценности.Например
Затем вы используете эти вспомогательные методы так часто, как вам это необходимо. (Если вы хотите быть необычным, вы можете попросить методы обновить атрибут, который держит текущую позицию, так что вам не нужно передавать Аргументpublic short getShort(byte[] buffer, int offset) { return (short) ((buffer[offset] << 8) | buffer[offset + 1]); }offset.)
Альтернативно, если бы Вы были не беспокоясь о накладных расходах, вы можете обернуть массив байтов в
ByteArrayInputStreamиDataInputStreamи использовать API последнего для чтения байтов, шорт, ints и т. д. IIRC,DataInputStreamпредполагает, что числа представлены в потоке в "сетевом порядке байтов"... это почти наверняка то, что предписывает спецификация DHCP.
Я немного опоздал, но есть класс ByteBuffer:
ByteBuffer b = ByteBuffer.wrap(request.getData()); byte opcode = b.get(); byte hwtype = b.get(); byte hw_addr_len = b.get(); byte hops = b.get(); int xid = b.getInt(); short seconds = b.getShort();Или, если вам нужно только одно поле:
ByteBuffer b = ByteBuffer.wrap(request.getData()); int xid = b.getInt(4);
Comments