Java 如果inputStream.available!=0是否尚未收到完整的数据?
我正在Android中使用BluetoothSocket(spp模式)。我发送的数据如下:Java 如果inputStream.available!=0是否尚未收到完整的数据?,java,android,sockets,bluetooth,Java,Android,Sockets,Bluetooth,我正在Android中使用BluetoothSocket(spp模式)。我发送的数据如下: Packet sent﹕ 0xAA 0x00 0x00 0x01 0x01 0x14 0x00 0x00 0xB6 0x34 /** * equals to java.io.DatainputStream.readFully */ public static void readFully(InputStream in, byte b[], int off, int len) throws IOExc
Packet sent﹕ 0xAA 0x00 0x00 0x01 0x01 0x14 0x00 0x00 0xB6 0x34
/**
* 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));
}
我得到的回应是:
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:
...
}
public void接收(int命令,字节[]数据){
如果(data.length!=0){
int设备=数据[1];
int PAR=数据〔5〕;
短尺寸数据=(短)((数据[6]和0xFF)
当inputStream.available!=0时,是否可能未收到完整的数据
它的Javadoc中没有任何关于“完整数据”的内容。Javadoc正确地指出,它是一种度量可以在不阻塞的情况下读取多少数据的方法
它不是:
- 输入流总长度的度量
- 消息边界的指示器
- 河流末端的指示器
Javadoc包含关于使用其值分配缓冲区的特定警告
如果需要读取超时,请使用Socket.setSoTimeout()。
“读取”的主要问题是不正确计算需要读取多少字节才能获得整个数据包。有几种主要的解决方案可以用来传递数据包,然后读取数据包:
a、 每个数据包都有一个指定长度的报头
b、 每个数据包的末尾都有一个预定义的分隔符,这有点像“0x00”(这意味着您不能在数据中使用这个字节)
c、 其他一些异国情调的
如我所见,你可以用a。然后你可以用这样的东西:
Packet sent﹕ 0xAA 0x00 0x00 0x01 0x01 0x14 0x00 0x00 0xB6 0x34
/**
* 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));
}
经过多年的开发,我仍然不知道如何使用InputStream.available():)通过数据传输超时关闭连接
或者,如果不可用,就像您的情况一样,一种计时器
(每次调用readFully方法后更新上次接收时间,并通过计时器检查当前时间和上次接收时间之间的差异)Android中的BluetoothSocket没有设置otimeout()方法。你的例子很有魅力!我接受了你的答案,因为你提供了一个很好的例子。谢谢!对不起,你能用你提供的例子解释一下你的计时器想法吗?我不完全理解,因为in.read()阻止执行,所以我不知道如何使用计时器来执行超时。非常感谢。in.read()阻止当前线程。这就是为什么需要另一个线程(例如计时器线程)定期检查读取线程在in.read()上花费的时间。请在in.read()之前将当前时间保存在易失性变量中调用,并检查当前时间与TimerTask.run中保存的值之间的差异。如果达到超时,请调用Socket.close()以断开连接并取消TimerTask.But Socket.close()将关闭套接字,可能我想继续使用该套接字。例如,为了再次发送NACK以发送数据。此外,一般来说,您可能会停止读取任何字节,包括标头的字节,包括数据大小的第二个字节…并且没有人能说问题何时解决,套接字的当前实例将工作ks之后(但您可以检查)。因此,如果数据包仍未完全读取,我建议在超时期间关闭套接字,并准备一个新的,然后尝试再次获取数据。只需将其设置为合理的值(10秒左右)