0

CサーバーからJavaクライアントに16進メッセージを渡そうとしています。通信は機能します。しかし、Javaクライアントで取得した16進値には、「ff」が追加されているようです。なぜこうなった?

C側では、送信したいバイトを(16進数で)出力すると、問題ないように見えます。

以下のコードを参照してください。

Cサーバー:

                    int datalen = 220;

                    /* create  outgoing message */
                    idx = 0;
                    en_outmsg[idx++] = FEB & 0xFF;
                    en_outmsg[idx++] = ENT & 0xFF;
                    en_outmsg[idx++] = CBA & 0xFF;
                    en_outmsg[idx++] = GRP & 0xFF;
                    en_outmsg[idx++] = OUTGOING & 0xFF;
                    en_outmsg[idx++] = (datalen & 0xFF00) >> 8;
                    en_outmsg[idx++] = datalen & 0xFF;

                    for(i= 0; i<39; i++){
                    printf("en_outmsg[%d] to send = %x\n",i, en_outmsg[i]);
                    }
                    en_outmsg[i+1] = '\n';


                    if (send(connected, en_outmsg, 40, 0) > 0)
                    {
                        printf("sending over\n");

                    }

Javaクライアント:

    while( (bytes =dis.read(buffer, 0, 40)) != -1){
        for(int index=38; index >= 0; index--)  {           

                System.out.println("index ="+index);
                System.out.println("buffer ="+Integer.toHexString(buffer[index]));
        }
        System.out.println("bytes="+bytes); 
        len = 0;
        len |= buffer[5];
        len = len << 8;
        len |=  buffer[6];
        System.out.println("value of len= "+len);
    }

OutPut:lenの値= -36 buffer [5] = 0 buffer [6] = 0xfffffffdc

更新しました

これが私のwiresharkの出力です(これはCサーバーがJavaクライアントにプッシュするものです):

行5の「00dc」はdatalen=220に対応し、Javaクライアントのlenにそのまま保存する必要があることに注意してください。したがって、Javaクライアントには明らかにエラーがあります。皆さんがおっしゃったように、私はInteger.toHexString(((int)buffer [index])&0xFF)を使用して印刷できます。ただし、バイト配列を正しい16進値で格納する必要があります。助けてください

0000  00 00 03 04 00 06 00 00  00 00 00 00 00 00 08 00   ........ ........
0010  45 00 00 5c b4 75 40 00  40 06 a0 ac c0 a8 b2 14   E..\.u@. @.......
0020  c0 a8 b2 14 09 60 b7 bb  fe bd 3a 2d fe 36 cc 8c   .....`.. ..:-.6..
0030  80 18 02 20 e5 c8 00 00  01 01 08 0a 00 04 8e 5f   ... .... ......._
0040  00 04 8e 5f 0a 01 01 16  01 00 dc 00 01 02 03 04   ..._.... ........
0050  05 06 07 08 09 0a 0b 0c  0d 0e 0f 2b 7e 15 16 28   ........ ...+~..(
0060  ae d2 a6 ab f7 15 88 09  cf 4f 3c d0               ........ .O<.    
4

4 に答える 4

1

Java のバイトは署名されています。したがって、最上位ビットが設定されている各値は負の値です。Integer.toHexString を呼び出したときに発生する整数に変換されると、符号が拡張されます。したがって、10000000b の場合、0x80 ではなく 1111111111111111111111110000000b または 0xFFFFFF80 になります。それは 32 ビットでは同じ負の値だからです。やっている

Integer.toHexString(((int)buffer[index]) & 0xFF)

それを修正する必要があります。

ところで、Java には符号なしの型はありません。

于 2011-05-05T13:34:27.080 に答える
1
But the hex value that I get on Java client seems to be appended with "FF"

Integer.toHexString(buffer[index] & 0xFF )あなたの問題を解決します。

于 2011-05-05T13:30:30.333 に答える
0

このような状況での最初のステップは、「回線上」で何が送信されているかを確認することです。可能であれば、 wiresharkまたはtcpdumpを使用して、送信されている内容を確認することを検討してください。そうすることで、何が期待どおりに機能していないかを把握できます。どちらも、ローカル IP にバインドされたソケットとループバック ソケットを監視できます。

しかし、見た目からすると、署名された/署名されていない衝突が起こっていることに同意します。

この出力がある場合は、「誰」に問題があるかを判断するのに役立ちます。

アップデート:

前述したように、マスクをオフにして最下位 8 ビットのみを使用する必要があります。これは次の方法で実行できます。

b = b & 0xFF

これをコードに 2 つの方法で導入できます。1 つは、各バイトに対して呼び出す単純な静的関数を使用する方法です。

public static int mask(int rawbyte)
{
    return (rawbyte & 0xFF);
}

もう 1 つは、DataInputStream.read() のラッパー関数で、バイトをバッファーに読み取り、すべてをマスクします。次のようになります。

public static int socket_read(DataInputStream dis, int arr[], int off, int len)
{
    b = new byte[len];
    int rv = dis.read(b, off, len);
    for(int i=0; i < len; i++)
    {
        arr[i] = ((int)b[i]) & 0xFF;
    }
    return rv;
}

最初の方法を選択した場合は、使用する buffer[] 値に対して mask() を呼び出す必要があります。そう

len |= buffer[5];

だろう

len |= mask(buffer[5]);

2 番目の方法を選択した場合は、buffer を byte 型の配列から int に変更します。

buffer = new int[...]

while ループを次のように更新できます。

while( (bytes = socket_read(dis, buffer, 0, 40)) != -1)

しかし、そうは言っても…

これらのいずれよりも優れたオプションは、DataInputStream の readUnsignedByte メソッドを利用することです。

自分で一度に 40 バイトをストリームから引き抜く必要がありますが、少しいじるよりも、何をしていたのかがより明確になります。これは、私の意見では好ましいアプローチです。

于 2011-05-05T14:08:23.697 に答える
0

符号ビット伝搬のように聞こえます。len およびその他の JAVA 変数は、署名されるべきではないときに署名されているように見えます。

于 2011-05-05T13:28:12.937 に答える