2012-04-26 5 views
0

Я посылаю байтовые массивы через сокет. Отправленные данные начинаются с 4 байтов, указывая длину следующего массива байтов.Чтение из входного потока сокета возвращает данные в неправильном порядке

// get the amount of data being sent 
byte[] lengthOfReplyAsArray = new byte[4]; 
forceRead(inputStream, lengthOfReplyAsArray); 
int lengthOfReply = byteArrayToInt(lengthOfReplyAsArray); 

// read the data into a byte array 
byte[] reply = new byte[lengthOfReply]; 
forceRead(inputStream, reply); 

Метод, используемый для считывания данных из InputStream:

private byte[] forceRead(InputStream inputStream, byte[] result) 
     throws IOException { 

    int bytesRead = 0; 
    int total = result.length; 
    int remaining = total; 

    while (remaining > 0) 
     remaining -= inputStream.read(result, bytesRead, remaining); 

    return result; 

} 

Метод, используемый, чтобы преобразовать массив байтов в целое число:

private int byteArrayToInt(byte[] byteArray) { 
    int result = 0; 

    for (int i = 0; (i<byteArray.length) && (i<8); i++) { 
     result |= (byteArray[3-i] & 0xff) << (i << 3); 
    } 
    return result;     
} 

Проблема заключается в том, что данные, не читается в том порядке, в котором он поступает. Первые 4 байта читаются просто отлично. Остальное перепутано. Я сделал дамп TCP, чтобы обеспечить правильное получение данных на клиенте. Кажется, что данные разделены на 4 TCP-пакета. InputStream возвращает первые 4 байта первого пакета, затем все данные четвертого пакета, последнюю часть (начиная с «длины последнего пакета») второго пакета и все данные третьего пакета. В этом порядке.

Кто-нибудь знает, что может вызвать эту проблему?

ответ

2

Ваша логика для чтения массив байтов не совсем верно:

От до docs:

Читает до LEN байт данных из входного потока в массив байтов . Делается попытка считывать столько, сколько len байтов, но может быть прочитано меньшее число . Число фактически прочитанных байтов возвращается как целое число.

и

Первый байт чтения сохраняется в элементе Ь [выкл], следующий в б [ВЫКЛ + 1], и так далее. Число прочитанных байтов, самое большее, равно len. Пусть k - количество фактически прочитанных байтов; эти байты будут , сохраненные в элементах b [off] через b [off + k-1], оставляя элементы b [off + k] через b [off + len-1] без изменений.

Однако, как ваша bytesRead переменная остается на 0 для всего цикла, любые данные из InputStream всегда пишется в начале вашего буфера, переписав данные, которые уже там.

Что будет работать лучше (проверка на -1 также гарантирует, что вы не вычтите -1 из оставшегося, если в потоке закончились данные досрочно, что приведет к увеличению remaining, что означало бы, что цикл будет работать без необходимости до тех пор, пока переполнение буфера составит remaining отрицательный):

while ((bytesRead = inputStream.read(result, total - remaining, remaining)) != -1 
    && remaining > 0) { 
    remaining -= bytesRead; 
+0

Большое спасибо. Вы только что сделали свой день (на самом деле целую следующую неделю тоже) :) – Francis

+0

Последний фрагмент кода очень полезен. Легко забыть проверить возвращаемое значение. Это простое 2-строчное решение. – user1132959