正如@Rocky提到的,它看起來像在你的代碼中混淆了位和字節。
如果您在二進制想到一個字節的可能有幫助:
Binary Decimal Hex
00000000 0 0x00
00000001 1 0x01
00110000 48 0x30
如果你看看二進制表示,算上從右側的位:一個字節有8位,所以第7位是最左邊的位和位0是最右邊的位。
十六進制(base-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和位4已設置。
爲了動態設置字節中的位,您需要使用布爾邏輯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
你還要在非操作
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),你只需要並與NOT(十六進制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 article)。
N.B. <<
運算符是左移運算符,它將位移入一個字節中,上述情況用於將兩個byte
組合成一個16位數字。左移8等效於由256
你的第二個點點不正確。 st [0]是一個包含8位的字節。 –
我認爲你正在混淆位與字節。如果你想設置位,你將需要使用位操作。 &= | = >><<等 –
我仍然感到困惑。我應該發送的最終數據包是什麼?僅僅是01 30 01 00? – YumYumYum