gpt4 book ai didi

java - 有可能当 inputStream.available != 0 时还没有收到完整的数据?

转载 作者:行者123 更新时间:2023-12-02 05:25:54 28 4
gpt4 key购买 nike

我在 Android 中使用 BluetoothSocket(在 spp 模式下)。我发送这样的数据:

Packet sent﹕ 0xAA 0x00 0x00 0x01 0x01 0x14 0x00 0x00 0xB6 0x34

我得到回复:

Packet received﹕ 0xAA 0x01 0x00 0x01 0x81 0x14 0x00 0x00 0x8F 0x34

但是当我尝试获得较大响应时,出现以下错误:

09-25 11:13:26.583    6442-6495E/AndroidRuntime﹕ FATAL EXCEPTION: Thread-1258
Process: es.xxx.xxxx, PID: 6442
java.lang.ArrayIndexOutOfBoundsException: length=178; index=178

错误在于:

public void receive(int command, byte[] data) {

if (data.length != 0) {
int device = data[1];
int par = data[5];
short sizeData = (short)(((data[6]&0xFF) << 8) | ((data[7]&0xFF)));
byte[] datos = new byte[sizeData];
for (int i = 0; i < sizeData; i++) {
datos[i] = data[8 + i]; // Here ocurred the error
}
switch (command) {
case RETURN_PING:
break;
case RETURN_MOUNT:
...
}

我从蓝牙读取输入数据的方法是(我在 StackOverflow 中做出响应后手动超时):

 public byte[] read(){
try {
int timeout = 0;
int maxTimeout = 10; // leads to a timeout of 2 seconds
int available = 0;
while((available = in.available()) == 0 && timeout < maxTimeout){
timeout++;
Thread.sleep(50);
}
receive = new byte[available];
in.read(receive);
return receive.clone();
} catch (IOException e) {
e.printStackTrace();
if (socket != null){
close();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}

所以,我的问题是:当in.available != 0时,有可能还没有收到完整的数据吗? (通过这种方式,方法 receive 读取字节 6 和 7,其中存储数据包长度,但是当此方法尝试迭代所有项目时,它会抛出 ArrayIndexOutOfBoundsException)。

最佳答案

  1. “读取”的主要问题是不正确地计算需要读取多少字节才能获取整个包。如何传递并读取数据包主要有以下几种解决方案:

a.每个数据包都有一个指定长度的 header

b.每个数据包的末尾都有一个预定义的分隔符,类似于“0x00”的魔法(这意味着您不能在数据中使用该字节)

c.其他一些异域风情

据我所知,您使用了 a.那么你可以使用这样的东西:

/**
* equals to java.io.DatainputStream.readFully
*/
public static void readFully(InputStream in, byte b[], int off, int len) throws IOException {
if (len < 0) {
throw new IndexOutOfBoundsException();
}
int n = 0;
while (n < len) {
final int count = in.read(b, off + n, len - n);
if (count < 0) {
throw new EOFException();
}
n += count;
}
}

public static int readByte (byte [] bytes, int offset) {
return ((int) bytes [offset]) & 0xFF;
}

public static short readShort(byte [] bytes, int offset) {
return (short)
(readByte(bytes, offset) << 8 |
readByte(bytes, offset + 1));
}

我看到你的 header 由 8 个字节组成。那么我建议执行以下操作:

byte[] header = new byte[8];
readFully(in, header, 0, header.length);

int device = readByte(header, 1);
int par = readByte(header, 5);
int sizeData = readShort(header, 6);

byte[] data = new byte[sizeData];
readFully(in, data, 0, sizeData);
// now we have the whole data
  • 经过多年的开发,我仍然不知道我们该如何使用 InputStream.available() :) 要通过数据传输超时关闭连接,您可以使用 http://docs.oracle.com/javase/7/docs/api/java/net/Socket.html#setSoTimeout(int)
  • 或者如果不可用,如您的情况,一种计时器

    http://developer.android.com/reference/java/util/Timer.html

    (每次调用readFully方法后更新上次接收时间,并通过定时器检查当前时间与上次接收时间的差值)

    关于java - 有可能当 inputStream.available != 0 时还没有收到完整的数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26035566/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com