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

时间:2015-11-12 13:10:26

标签: java sockets tcp bytearray

一段Java代码驻留在服务器上,该服务器需要来自一块硬件的大约64字节信息,通过TCP发送。该数据包有一个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(data)是否正确转储接收到的缓冲区,我知道该缓冲区应该是可读的HEX字符串?

注意:此问题的根源在于:Java TCP Socket Byte Heap Memory Issue

2 个答案:

答案 0 :(得分:2)

如果对方使用DataInputStream或其格式正确,则仅使用DataOutputStream。例如,整数可以编码big-endian or little-endian - DataOutputStream使用big-endian表示法,如果另一方使用不同的编码,则不能使用DataInputStream。如果需要,使用InputStream.read()可以为您提供更多控制。

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

答案 1 :(得分:0)

您可以使用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

但我建议您使用InputStream.read()代替DateInputStream

关注@Jiri回答。