我有一个Java应用程序正在从正在接收不同大小的XML的TCP套接字读取数据。给定数据包的前5个字节应该表示剩余消息的大小。如果我手动创建一个大字节[]并读取数据,我可以成功读取消息和xml。
以下是生成数据的应用程序手册中的说明:
每条消息前面都有一条消息大小指示符 使用网络字节顺序方法的32位unsinged整数。对于 示例:\ x05 \ x00 \ x00 \ x00 \ x30 \ x31 \ x30 \ x32 \ x00表示消息 5个字节的ack的大小包括第五个消息字节' \ 0'。该 size指示符指定大小指示符后的所有内容 本身。
但是,我无法弄清楚如何将前5个字节解码为一个整数,我可以使用它来正确调整字节[]的大小以读取其余的消息。我得到随机结果:
以下是我用来解析消息的代码:
DataOutputStream out = new DataOutputStream(clientSocket.getOutputStream());
BufferedInputStream inFromServer = new BufferedInputStream(clientSocket.getInputStream());
byte[] data = new byte[10];
inFromServer.read(data);
String result = new String(data, "ISO-8859-1");
Logger.info(data+"");
//PROBLEM AREA: Tried reading different byte lengths but no joy
//This should be a number but it never is. Often strange symbols
byte[] numeric = Arrays.copyOfRange(data,1,5);
String numericString = new String(numeric, "ISO-8859-1");
//Create a huge array to make sure everything gets captured.
//Want to use the parsed value from the start here
byte[] message = new byte[1000000];
inFromServer.read(message);
//This works as expected and returns correctly formatted XML
String fullMessage = new String(message, "ISO-8859-1");
Logger.info("Result "+result+ " Full message "+fullMessage);
答案 0 :(得分:3)
长度看起来像是小端。您仍然可以使用DataInputStream,但必须交换字节。如果您使用NIO的SocketChannel和ByteBuffer,您可以设置字节顺序,但这可能更难使用。
// only do this once per socket.
DataInputStream in = new DataInputStream(
new BufferedInputStream(clientSocket.getInputStream()));
// for each message.
int len0 = in.readInt();
int len = Integer.reverseBytes(len0);
assert len < 1 << 24;
byte[] bytes = new byte[len];
in.readFully(bytes);
String text = new String(bytes, "ISO-8859-1").trim();
int number = Integer.parseInt(text);
答案 1 :(得分:2)
网络字节顺序又名big-endian。但看到你的数据似乎,实际上是小端使用。至少5
看起来像little-endian中的前4个字节,但不是big-endian。所以你需要读取那些字节,考虑little-endian并转换为long来考虑“unsigned-ness”。
public static void main(String[] args) throws IOException {
DataInputStream inFromServer = new DataInputStream(new BufferedInputStream(null));
int iSize = inFromServer.readInt();
iSize = Integer.reverseBytes(iSize); //read as little-endian
long count = Integer.toUnsignedLong(iSize); //unsigned int
}