2016-01-25 1 views
1

У меня есть приложение Java, которое считывает данные из сокета TCP, который получает XML разного размера. Первые 5 байтов данного пакета должны указывать размер оставшегося сообщения. Я могу успешно прочитать сообщение и xml, если вручную создать большой байт [] и прочитать данные.Разбор int с начала байт [] из гнезда

Вот инструкции из руководства для приложения, создающее данные:

Каждого сообщение предшествует индикатор размера сообщения, которое является 32-битным Беззнаковым целым числом, используя сеть байт метода заказа , Для примера : \ x05 \ x00 \ x00 \ x00 \ x30 \ x31 \ x30 \ x32 \ x00 указывает сообщение размер ack, который равен 5 байтам, включая пятый байт сообщения '\ 0'. Индикатор размера указывает все, что соответствует индикатору размера .

Однако я не могу понять, как декодировать первые 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); 
+1

длина сообщения в первых четырех не пять байтов – wero

+1

, что «сеть байт порядка» выглядит подозрительно, как мало-Endian, также известный как * не * Сетевой порядок байт. –

+0

Указания неверны. Это не 5 в сетевом порядке. Если это так, вы можете использовать 'DataInputStream.readInt()'. Как бы то ни было, вы должны жаловаться поставщику («искать разъяснения»). И это не XML. – EJP

ответ

3

Длина выглядит он немного младшему. Вы все равно можете использовать DataInputStream, но вы должны поменять байты. Если вы использовали Nocket 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); 
+0

Это правильно, поскольку оно относится к документации, размещенной в вопросе. Тем не менее, однако, документация не соответствует действительности. В документе мало аргумента, но данные идут по большому счету. –

+0

@JoeW в этом случае вы можете сбросить 'reverseBytes' –

2

Сетевой порядок байтов - это big-endian. Но, видя ваши данные, кажется, что на самом деле используется little-endian. По меньшей мере 5 будут выглядеть так, как первые 4 байта в little-endian, но не в 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 
} 
+0

пропустили это. :) –

+0

« Сетевой порядок байтов »определен в RFC как big-endian. – EJP