3

Cで記述されたネイティブプログラムからSockets、つまりwinsockインターフェイスを介してデータを送信する必要があります。その後、そのデータはJavaプログラムによって受信されます。Javaプログラムは、順序を認識しているデータのパケットを受信し、何らかの処理を行います。これは、socket.Read()から受け取ったintを次のように受け取ります。client_socket.getInputStream().read()

Read()から返されたそのintデータの処理は、期待されるデータ型を取得するために解析されます。基本的には、受信したバルクデータのスライスです。read()関数が一度に4バイト(32ビットのjava intサイズ)を読み取ると想定することしかできません。そこで、その4バイト(Javaタイプではなく8ビット)を4つのJavaショートに分割して、それらが表す符号なしの値を正しく表現できるようにします。たとえばuint16が必要な場合は、4つのショーツを入手した後、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をスローします

入力ストリームからデータの次のバイトを読み取ります。値byteは、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.
于 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 に答える