有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

从数据包头设置Java字节数组大小的socket

一段Java代码驻留在一台服务器上,期望从一块硬件通过TCP发送大约64字节的信息。数据包有一个10字节的报头。第一个字节是协议标识符,第二个两个字节给出数据包中的总字节数,包括所有头字节和校验和。最后7个字节是UID

服务器代码:

public void run () throws Exception
    {

        //Open a socket on localhost at port 11111
        ServerSocket welcomeSocket = new ServerSocket(11111);


        while(true) {

            //Open and Accept on Socket
            Socket connectionSocket = welcomeSocket.accept();

            //Alt Method

            DataInputStream dis = new DataInputStream(connectionSocket.getInputStream());

            int len = dis.readInt();
            byte[] data = new byte[len];
            if (len > 0) {
                dis.readFully(data);
            }
            System.out.println("Recv[HEX]: " + StringTools.toHexString(data));
    }
}

问题是我的readInt()行,它占用前四个字节,但是我需要根据后两个字节确定长度。如何做到这一点

其次,是我的stringTools。toHexString(数据)是否正确转储我知道应该作为十六进制字符串可读的接收缓冲区

注意:这个问题的根源在这里:Java TCP Socket Byte Heap Memory Issue


共 (2) 个答案

  1. # 1 楼答案

    仅当另一方使用DataInputStream或其确切格式时才使用DataOutputStream。例如,整数可以被编码big-endian or little-endian-DataOutputStream使用大端符号,如果另一端使用不同的编码,则不能使用DataInputStream。如果需要,使用InputStream.read()可以提供更多控制

    现在,由于您所说的消息格式以一个字节作为协议标识符开始,您首先需要将其作为一个字节(dis.readByte()InputStream.read())读取,并检查协议是否符合您的预期,或者处理不同的协议。然后你阅读信息的长度等等

  2. # 2 楼答案

    可以使用ByteBuffer读取最后两个字节中的int

    import static java.lang.System.out;
    import java.nio.ByteBuffer;
    class B {
        public static void main( String ... args ) {
            // test value
            int a = 1238098;
    
            // convert it into an arrays of bytes
            ByteBuffer b = ByteBuffer.allocate(4);
            b.putInt(a);
            byte [] r = b.array();
            // read last two 
            int size = ByteBuffer.wrap(new byte[]{0x0,0x0, r[2], r[3]}).getInt();
    
            // print it 
            out.println("Original: " + String.format("%32s%n" , Integer.toString(a,2)).replace(' ', '0'));
            out.printf("Last two: %32s%n" , Integer.toString(size,2));
            out.printf("Decimal : %d%n" ,  size );
        }
    }
    

    输出:

    Original: 00000000000100101110010001010010
    
    Last two:                 1110010001010010
    Decimal : 58450
    

    不过,我建议大家遵循@Jiri-answer,使用InputStream.read()而不是DateInputStream阅读