【问题标题】:C server to Java client socket read passed in short valueC 服务器到 Java 客户端套接字读取以短值传递
【发布时间】:2015-04-03 22:56:54
【问题描述】:

我很难从 C 服务器传递一个短值。我在另一端收到的是“垃圾”,我似乎无法将其转换为有用的东西。

我认为影响它的因素

  1. 2s 补码
  2. 可能的 ASCII 或 UTF-8 编码

从 C 代码开始:

        // Read 10 bit value into short
        unsigned short ret = decideActionCall(buffer);  
        unsigned char lsb = (unsigned char) ret;
        unsigned char msb = (unsigned char) (ret >> 8);

        printf("msb,lsb = %02x,%02x\n",msb, lsb);

        /**
        char retString [4];
        retString[0] = msb;
        retString[1] = lsb;
        retString[2] = '\n';
        retString[3] = '\0';
        */

        unsigned short retString1[1];
        retString1[0] = ret;

        printf("msb,lsb = %d,%d\n",retString[0],retString[1]);

        printf("String to send: <%s>\n",retString1);
        //if (write(newsockfd, retString, 3) < 0) {
        //  error("Error sending response to the server");
        //}
        if (write(newsockfd, &retString1, 2) < 0) {
          error("Error sending response to the server");
        }
        if (write(newsockfd, "\r",1) < 0) {
          error("Error sending response to the server");
        }

终端输出是

START-----------------------------

0 0
136 0x88
ADC3 = 136

END-----------------------------
decideActionCall() ret value: 136
msb,lsb = 00,88
msb,lsb = 0,136
String to send: <�>

所以“ret”的返回值是一个介于 0 和 1023 (0x3FF) 之间的值。这 10 位需要从 C 服务器传输到客户端。我尝试了两种实现方式,将它们作为 8 位字符 (retString) 或一个 16 位短字符 (retString1) 发送。 Sizeof(char) == 1sizeof(short) == 2

Java 代码(各种尝试解析它):

BufferedReader bufIn = new BufferedReader(new InputStreamReader(in));
String response = bufIn.readLine();

char [] hello = response.toCharArray();
for (char a : hello) {
    short shortA = (short) (a & 0x3FF);
    System.out.println(a + " = " + (int)a + " = " + shortA);


    //System.out.println((int)a);
    //System.out.println(Integer.valueOf(a+"",10));
    }

byte test[] = response.getBytes("UTF-8");

StringBuilder sb = new StringBuilder();
for (byte b : test) {
     sb.append(String.format("%02X ", b));
}
System.out.println(sb.toString());

byte b05 = 0x00;
byte b06 = 0x00; // MSB, positive as < 0x80

int i = 0;
for (byte a : test) {
    //System.out.println(short1);
    System.out.println("byte: " + a);
    //System.out.println(Integer.valueOf(a+"",10));

    if (i == 0 ) {
        b05 = a;
    } else {
        b06 = a;
    }

    i++;
    }

    System.out.println("i = "  + i);

    byte[] byteTabDay = new byte[2];
    byteTabDay[0] = b05;
    byteTabDay[1] = b06;

    BigInteger temp = new BigInteger(test);
    System.out.println(temp);
    System.out.println(temp.intValue());
    System.out.println(temp.shortValue() + 65536);

    BigInteger temp2 = new BigInteger(byteTabDay);
    System.out.println(temp2);
    System.out.println(temp2.shortValue() + 65536);

Java 示例输出(android logcat):

I/System.out﹕ response: ���
I/System.out﹕ here: � 65533
I/System.out﹕ ascii: 65485 65581
I/System.out﹕  � = 65533 = 1021
I/System.out﹕ �� = 0 = 0
I/System.out﹕ EF BF BD 00
I/System.out﹕ byte: -17
I/System.out﹕ byte: -65
I/System.out﹕ byte: -67
I/System.out﹕ byte: 0
I/System.out﹕ i = 4
I/System.out﹕ -272646912
I/System.out﹕ -272646912
I/System.out﹕ 48384
I/System.out﹕ -4352
I/System.out﹕ 61184

问题:

  1. 我应该如何正确读取套接字?
  2. 如何正确读取 10 位? (我试过用 0x3FF 屏蔽字符)
  3. 二进制补码是否会导致问题?

谢谢,

【问题讨论】:

  • 如果你想要一个 16 位整数,不要使用 'short',因为 short 的大小是实现定义的。改用 'uint16_t' - 它被定义为 16 位。您还希望按网络顺序读取和写入多字节整数。还可以尝试以十六进制打印您的 Java 输出。
  • 感谢您的回复。我将值更改为 uint16_t 和 unint8_t (如果可用)。我还使用 1 和 0 给出的链接将其更改为网络字节顺序。我还打印了十六进制,但仍然混乱。我实施了 EJP 建议的更改,并且似乎奏效了。
  • 另外,考虑使用 Protocol Buffers 之类的东西,而不是手动推送二进制数据。

标签: java c sockets network-programming unsigned


【解决方案1】:
  1. 您正在接收二进制文件,因此您根本不应该使用Reader。你应该使用DataInputStream.readShort().
  2. 没错。
  3. 没有。

【讨论】:

  • 感谢您的回复。我实施了这个改变,我相信它是解决办法。我一直收到正确的值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-24
  • 1970-01-01
  • 1970-01-01
  • 2012-06-05
  • 2020-01-23
  • 2017-05-26
  • 1970-01-01
相关资源
最近更新 更多