首页 文章

TCP / IP客户端错误地读取输入流字节数组

提问于
浏览
2

我正在创建一个Java客户端程序,它向服务器发送命令,服务器发回确认和响应字符串 .

响应以这种方式发送回客户端 - > server:cmd_string

服务器 - >客户端:ack_msg(06)

server - > client:response_msg

Client code

public static void readStream(InputStream in){

byte[] messageByte = new byte[20];// assuming mug size -need to
                                        // know eact msg size ?
    boolean end = false;
    String dataString = "";
    int bytesRead = 0;

    try {
        DataInputStream in1 = new DataInputStream(in);
        // while ctr==2 todo 2 streams
        int ctr = 0;
        while (ctr < 2) {//counter 2 if ACK if NAK ctr=1 todo
            bytesRead = in1.read(messageByte);

            if (bytesRead > -1) {
                ctr++;
            }
            dataString += new String(messageByte, 0, bytesRead);

            System.out.println("\ninput byte arr "+ctr);
            for (byte b : messageByte) {
                char c=(char)b;
                System.out.print(" "+b);
            }
        }


        System.out.println("MESSAGE: " + dataString + "\n bytesread " + bytesRead + " msg length "
                + dataString.length() + "\n");
        char[] chars = dataString.toCharArray();
        ArrayList<String> hex=new ArrayList<>();
        // int[] msg ;
        for (int i = 0; i < chars.length; i++) {
            int val = (int) chars[i];
            System.out.print(" " + val);
        hex.add(String.format("%04x",  val));
        }
        System.out.println("\n"+hex);

    } catch (Exception e) {
        e.printStackTrace();
    }
    // ===

}

Output

client Socket created .. 
     response:

     input byte arr 1
     6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    input byte arr 2
     2 -77 67 79 -77 48 -77 3 -116 0 0 0 0 0 0 0 0 0 0 0
    MESSAGE: ##³CO³0³##
     (where # is some not supported special character )
     bytesread 9 msg length 10

     dec: 6 2 179 67 79 179 48 179 3 338
    hex: [0006, 0002, 00b3, 0043, 004f, 00b3, 0030, 00b3, 0003, 0152]
    bytes: 2 -77 67 79 -77 48 -77 3 -116 0 0 0 0 0 0 0 0 0 0 0 (bytes recieved in 2nd packet)
    connection closed

问题:我正在读取最后一个值不正确,我已经使用wireshark验证服务器已将响应发送回06 02 b3 43 4f b3 30 b3 03 8c我正在如何正确读取最后一个值 . 阅读流有问题吗?

EDIT

其余的响应被正确读取但最后一个字符应为8c但读为0152Hex

来自服务器的响应:06 02 b3 43 4f b3 30 b3 03 8c

通过程序阅读:[0006,0002,000b3,0043,004f,00b3,0030,00b3,0003,0152]

阅读最后一个字符的问题

EDIT 2

Response is received as 2 packets/streams

packet 1 byte arr :  6 (ACK)

packet 2 byte arr:  2 -77 67 79 -77 48 -77 3 -116 (response)

complete response read by client

dec: 6 2 179 67 79 179 48 179 3 338
  hex: [0006, 0002, 00b3, 0043, 004f, 00b3, 0030, 00b3, 0003, 0152]

谢谢

1 回答

  • 1

    这个问题的问题是 signed 变量与 unsigned 变量的问题 . 当你在计算机存储器中有一个数字时,它由一堆位表示,每个位为0或1.字节通常为8位,短路为16等 . 在 unsigned 数字中,8位将使您从正0到255,但不是负数 .

    这是 signed 数字的来源 . 在带符号的数字中,第一位告诉您以下位是表示负值还是正值 . 所以现在你可以使用8位代表-128到127.(请注意,正范围减半,从255到127,因为你的范围的一半到负数) .

    那么现在如果将 signed 转换为 unsigned 会发生什么?根据你的方式,事情可能会出错 . 在上面的问题中,代码 char c=(char)b; 正在将 signed 字节转换为 unsigned char . 执行此操作的正确方法是在将其转换为char之前"make your byte unsigned" . 你可以这样做: char c=(char)(b&0xFF); more info on casting a byte here .

    基本上,你可以记住,除了char之外,所有的java数字都是有符号的,你需要做的就是粘贴 &0xFF 以使其适用于一个字节, 0xFFFF 使其适用于短路等 .

    有关其工作原理的详细信息如下 . 调用&表示bitwise and0xFF 是255的十六进制.255高于有符号字节的限制(127),因此数字 b&0xFF 被java升级为short . 但是,短符号位在第16位,而字节符号位在第8位 . 所以现在字节符号位在短路中变为正常'data'位,因此字节的符号基本上被丢弃 .

    如果你进行普通的转换,java会认识到像上面那样直接进行位转换会意味着你丢失了这个符号,并且java希望你不喜欢它(至少,这是我的假设),所以它会为你保留符号 . 所以如果这不是你想要的,你明确告诉java要做什么 .

相关问题