2011-10-23 91 views
2

我有一个要求,即通过套接字(即winsock接口)以C编写的原生程序发送数据。该数据然后由Java程序接收。 Java程序接收知道其顺序的数据分组并进行一些处理。它需要从套接字接收到的int.Read(),如client_socket.getInputStream().read()将uintN数据类型从C传输到Java(套接字编程)

对从Read()返回的int数据进行处理以解析期望的数据类型。基本上它是对所收到的批量数据进行分割。我只能假设read()函数每次读取4个字节(32位java int大小)。因此,我继续将4个字节(8位而不是Java类型)分成4个Java短语,以便我可以正确表示它们表示的无符号值。 当我有4个短裤,如果我知道我想要一个uint16,我只是连接两条短裤

问题是我在做某些错误的位操作,因为我认为会这样。 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++; 

} 

回答

1

阅读符号短号码最简单的方法是使用DataInput.readUnsignedShort()。

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

这使用big-endian或网络endian。如果您使用的是小端(例如,在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(); 
} 

你真的需要发送无符号短值流吗?更经常使用的流是无符号字节,这些更简单。

+0

不应该sc.read(bb)> 0是sc.read(bb)> = 0?阅读可能会返回0. –

+0

如果它阻塞,但不管怎样都会改变它。 ;) –

+0

java是如此的辉煌。我可以更改缓冲区中的endiannes。还有很多关于缓冲库的东西我不知道 –

3

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

不,你不能假设。该documentation for InputStream.read()说:

公共抽象INT阅读() 抛出IOException异常

读取数据从输入流的下一个字节。值字节在0到255范围内返回为int。如果因为已到达流的末尾而没有可用的字节 ,则返回值-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. 
+0

所以这意味着我看到的4号实际上是字节本身。如果是这样,那么简单,我感觉不好 –