Как уже упоминалось @Rocky, похоже, что в вашем коде вы путаете биты и байты.
Это может помочь, если вы думаете о байте в двоичном виде:
Binary Decimal Hex
00000000 0 0x00
00000001 1 0x01
00110000 48 0x30
Если вы посмотрите на двоичное представление, вы посчитаете биты справа: байт имеет 8 битов, поэтомубит 7 - самый левый бит, а бит 0 - самый правый бит.
Причина, по которой шестнадцатеричная (базовая-16) запись так удобна, заключается в том, что преобразовать двоичный код в шестнадцатеричный легче, чем двоичный.в шестнадцатеричное число.
Возьмите двоичное число 00110000. Если вы разделите их на две части (0011) и (0000), называемые верхним полубайтом (биты 7-4) и нижним полубайтом (биты 3-0),Затем вы можете легко преобразовать два полубайта в гекс:
Nibble Hex Decimal
0000 0 0
0001 1 1
0010 2 2
0011 3 3
0100 4 4
0101 5 5
0110 6 6
0111 7 7
1000 8 8
1001 9 9
1010 A 10
1011 B 11
1100 C 12
1101 D 13
1110 E 14
1111 F 15
Соединяя два полубайта, вы можете увидеть взаимосвязь между шестнадцатеричным и двоичным:
Binary
0011 1100
Hex
3 C
so binary 00110100 = hex 34 = dec 60
Итак, вернемся к вашему двоичному файлуформат:
В пакете запроса вы получаете ответ (шестнадцатеричный код 30), поэтому, если вы преобразуете его в свой бит:
Hex 30 = binary 0011 0000
Вы можете видеть, что биты 5 и 4set.
Чтобы динамически устанавливать биты в байте, вам нужно использовать логическую логику AND и OR.Ниже приведены результаты для и и или для одного бита:
Bit Bit Result Result Result
A B AND OR XOR
0 0 0 0 0
0 1 0 1 1
1 0 0 1 1
1 1 1 1 0
У вас также есть операция NOT
Bit Result NOT
0 1
1 0
С несколькими битами вы просто выполняете операцию надкаждый бит (биты от 7 до 0), например:
01101010 (hex 6A)
AND 11100110 (hex E6)
= 01100010 (hex 62)
01101010 (hex 6A)
OR 11100110 (hex E6)
= 11101110 (hex EE)
NOT 00111001 (hex 3B)
= 11000110 (hex C6)
Итак, помня об этом, вы можете использовать следующие операции для установки и очистки отдельных битов в байте:
Есливы хотите убедиться, что бит 6 установлен (1), вам просто нужно ИЛИ его с 01000000 (шестнадцатеричное 40)
xxxxxxxx (any value)
OR 01000000 (hex 40)
= x1xxxxxx
Если вы хотите убедиться, что бит 6 сброшен (0), вы простонужно И это с НЕ (шестнадцатеричное 40), поэтому
NOT 01000000 (hex 40)
= 10111111 (hex BF)
xxxxxxxx (any value)
AND 10111111 (hex BF)
= x0xxxxxx
Чтобы поместить все это в код Java, у вас есть следующие бинарные операторы:
- |двоичное ИЛИ
- и двоичное И
- ~ двоичное НЕ
Итак, если вы хотите установить бит в байте:
byte anyByte;
anyByte = anyByte | 0x40;
который можно сократить до
anyByte |= 0x40;
Если вы хотите сбросить бит:
anyByte &= ~0x40;
Если вы хотите проверить, установлен ли бит, вы должны использовать следующее:
if ((anyByte & 0x40) == 0x40) ...
Если вы хотите проверить, были ли установлены бит 4 и 1, вы должны сделать следующее:
if ((anyByte & 0x12) == 0x12) ...
Почему 0x12?Потому что hex 12
- это binary 0001 0010
, который «маскирует» биты 4 и 1.
Вернуться к вашему вопросу:
Чтобы отправить правильную командную строку, вам просто нужно создать правильнуюМассив байтов, как указано в руководстве, хотя я надеюсь, что теперь стало понятнее, как устанавливать биты в байтах:
Socket s = new Socket("192.168.1.2", 49137);
InputStream in = s.getInputStream());
// send the request
// (Note, for different requests, you'll need different, byte arrays and may
// even have different lengths (can't tell without having seen the whole manual)
byte[] st = new byte[] { 0x01, 0x30, 0x01, 0x00 };
OutputStream out = s.getOutputStream();
out.write(st);
out.flush();
// read the first header byte (bits indicate the rest of the header structure)
byte header = (byte)in.read();
// bit 1 shows whether the header represented in 2 bytes
boolean header2Byte = (header & 0x2) != 0;
// bit 2 shows whether the length is represented in 2 bytes
boolean len2Byte = (header & 0x4) != 0;
if (header2Byte) {
// need to read the extra header (discarded here)
in.read();
}
// missed off reading the command byte/s
int len = 0;
if (len2Byte) {
byte[] lenByte = new byte[2];
in.read(lenByte);
if (isLittleEndian) {
len = (lenByte[1] << 8) + lenByte[0];
} else {
len = (lenByte[0] << 8) + lenByte[1];
}
} else {
// only one byte signifies the length
len = is.read();
}
byte[] data = new byte[len];
in.read(data);
// it is unclear what format the data, has but if it is a string, and encoded as
// UTF-8, then you can use the following
String stringData = new String(data, "UTF-8");
System.out.println(stringData);
// note, try-catch-finally omitted for brevity
in.close();
out.close();
s.close();
Обратите внимание, я не использую DataInputStream здесь, так как способ, которым Java кодирует целые числа, может отличатьсяот того, как устройство кодирует его целые числа.Например, в Java и целое число составляет 4 байта и Big Endian (см. Также эту статью SO ).
NB Оператор <<
является оператором левого сдвига, который сдвигает биты вБайт и вышеприведенный случай используются для объединения двух byte
в 16-битное число.Сдвиг влево на 8 эквивалентен умножению на 256.