java - 处理二进制数据包

标签 java networking

我编写了这个数据包处理程序,但我可以想象它会卡住或无法读取不完整数据的场景。我的问题是:

  1. 我应该使用两个缓冲区,一个用于当前传入数据,另一个用于附加不完整的数据?
  2. 我是不是太复杂了?

代码:

byte[] buffer;
int bufferLength;
int bytesRead;

buffer = new byte[1024];

while (bluetoothConnected) {
    try {
        // Wait for packet header
        if (mmInStream.available() >= 8) {
            bufferLength = mmInStream.read(buffer);
            bytesRead = 0;

            // Parse every packet
            while (true) {
                int commandType = ByteBuffer.wrap(buffer, 0, 2).order(ByteOrder.LITTLE_ENDIAN).getShort();
                int payloadSize = ByteBuffer.wrap(buffer, 2, 2).order(ByteOrder.LITTLE_ENDIAN).getShort();
                int packetSize = PACKET_HEADER_SIZE + payloadSize;

                // Break if payload is incomplete
                if (bufferLength < (bytesRead + packetSize)) {
                    // Append to other buffer
                    break;
                }

                byte[] packet = new byte[packetSize];
                System.arraycopy(buffer, bytesRead, packet, 0, packetSize);

                parsePacketSequence(socket, packet);
                bytesRead += packetSize;

                // Break if all bytes are read
                if (bufferLength == bytesRead)
                {
                    break;
                }

                // Break if more bytes are needed
                // Packet header incomplete
                if ((bufferLength - bytesRead) < PACKET_HEADER_SIZE)
                {
                    // Append to other buffer
                    break;
                }
            }
        }
    } 
    catch (IOException e) {
        bluetoothConnected = false;
        Log.d(TAG, "Error " + e);
        break;
    }
}

最佳答案

  1. Should I use two buffers, one for the current incoming data and other to append incomplete data to?

没有。

  1. I'm being stupidly over-complicated?

是的。

这是使用 DataInputStream 的简单版本:

DataInputStream din = new DataInputStream(mmInStream);

while (bluetoothConnected) {
    try {
        // Read packet header
        int commandType = swap(din.readShort());
        int payloadSize = swap(din.readShort());
        int packetSize = PACKET_HEADER_SIZE + payloadSize;
        byte[] packet = new byte[packetSize];
        din.readFully(packet);
        parsePacketSequence(socket, packet);
    } 
    catch (IOException e) {
        bluetoothConnected = false;
        Log.d(TAG, "Error " + e);
        break;
    }
}

将小尾数字节顺序中的短整型转换为 Java 字节顺序的 swap() 方法留给读者作为练习。

注意,如果 parsePacketSequence() 不知道 commandType,我不明白它如何工作。

E&OE

关于java - 处理二进制数据包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37424414/

相关文章:

java - 在 Camunda BPMN 引擎中传递冗长的文本 - http 连接器

iphone - 使用 NSMutableURLRequest 通过 http post 发送文件时出现网络错误

c - 如何更改我的服务器以便多个客户端可以访问服务器中的共享数据?

networking - 如何将DNS重定向到不同的端口

c++ - 如何获取(Linux)机器的 IP 地址?

linux - nf_ct_get(skb,&ctinfo) 函数获取 IPv6 udp 数据包的 netfiter conntrack 'struct conn'

java - 如何从 web start 下运行的客户端获取 Java 堆栈跟踪?

java - 使用注释来监视/记录/报告线程访问给定方法的 Java 工具?

java - 数据输入流

java - 未执行方法参数上的自定义注释