Java 如果inputStream.available!=0是否尚未收到完整的数据?

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

我正在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 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秒左右)