3

我需要通过 Sockets 从用 C 编写的本机程序发送数据,即 winsock 接口。然后,该数据由 java 程序接收。Java程序接收到一个它知道顺序的数据包并进行一些处理。它需要从 socket.Read() 收到的 int 像client_socket.getInputStream().read()

从 Read() 返回的 int 数据的处理被解析以获得预期的数据类型。基本上它是对收到的批量数据的切片。我只能假设 read() 函数一次读取 4 个字节(32 位 java int 大小)。所以我继续将 4 个字节(8 位不是 Java 类型)分成 4 个 Java 短裤,这样我就可以正确地表示它们所代表的无符号值。在我有 4 条短裤后,如果我知道我想要一个 uint16,我只需将 2 条短裤连接起来

问题出在某个地方,我正在做一些错误的位操作,但并没有像我想象的那样奏效。下面是 C 代码和 Java 代码,即使它不起作用,它也非常简单。输出是我不明白为什么会这样。

0 0   0 0    0 1     0 0     0 2     0 0     0 3     0 0     0 4 {...}

C 代码编辑了初始化部分:

uint16_t buffer[255] = {};
uint16_t *current_pointer = buffer;
for(uint16_t index = 0; index < 255; index++) {
    *current_pointer = index;
    current_pointer++;
}
Write(client_socket, (char *)buffer, sizeof(buffer));

Java 代码也被修改:

public final short[] JavaIntToUint8Array(int unsigned_int) {
    return new short[] { (short)((unsigned_int & 0xFF000000L) >> 24),
                (short)((unsigned_int & 0x00FF0000L) >> 16),
                (short)((unsigned_int & 0x0000FF00L) >> 8),
                (short)((unsigned_int & 0x000000FFL))};
}
public final int[] JavaIntToUint16(int unsigned_int) {
    short uint8_array[] = JavaIntToUint8Array(unsigned_int);
    return new int[] { (int)(uint8_array[0] << 8) | (int)uint8_array[1],            
        (int)(uint8_array[2] << 8) | (int)(uint8_array[3]) };
}

...

while (index < 255) {
        read_data = data_input.read();
        System.out.print(" ");
        System.out.print(JavaIntToUint16(read_data)[0]);
        System.out.print(" ");
        System.out.print(JavaIntToUint16(read_data)[1]);
        System.out.print("\t");
        index++;

}
4

2 回答 2

3

我只能假设 read() 函数一次读取 4 个字节(32 位 java int 大小)

不,你不能这样假设。的文档InputStream.read()说:

public abstract int read() 抛出 IOException

从输入流中读取数据的下一个字节。值字节作为 int 返回,范围为 0 到 255。如果由于到达流的末尾而没有可用的字节,则返回值 -1。此方法会一直阻塞,直到输入数据可用、检测到流结束或引发异常。

A subclass must provide an implementation of this method.

Returns:
    the next byte of data, or -1 if the end of the stream is reached.
于 2011-10-23T13:33:41.297 回答
1

读取无符号短数字的最简单方法是使用 DataInput.readUnsignedShort()。

DataInputStream dis = new DataInputStream(data_input);
int num = dis.readUnsignedShort();

这使用大端或网络端。如果您使用的是小端(例如在 x86/x64 处理器上),您可以自己更改字节顺序或使用 ByteBuffer 来完成。

// using NIO
SocketChannel sc = SocketChannel.open(new InetSocketAddress("localhost", 12345));
ByteBuffer bb = ByteBuffer.allocateDirect(32*1024).order(ByteBuffer.LITTE_ENDIAN));
while(sc.read(bb) >= 0) {
    bb.flip();
    while(bb.remaining() > 1) {
       int num = bb.getShort() & 0xFFFF;
    }
    bb.compact();
}

您真的需要发送无符号短值流吗?更常用的流是无符号字节,它们更简单。

于 2011-10-23T13:36:40.643 回答