2016-01-19 2 views
0

Ive прочитал много руководств и сообщений о java InputStream и данных чтения. Ive установил реализацию клиента и сервера, но у меня возникли странные проблемы, когда чтение переменной «полезная нагрузка» с клиентом несовместимо.Java-сокет InputStream.read() не ведет себя так, как ожидалось

То, что я пытаюсь сделать, это передать до 100 кбайт макс в одной логической полезной нагрузке. Теперь я проверил, что стек TCP не отправляет один mahousive 100kB-пакет от клиента. Я играл с разными форматами чтения в соответствии с предыдущими вопросами о чтении InputStream, но я почти разукрасил мои волосы, пытаясь заставить его сбросить правильные данные.

Позволяет, например, сказать, что клиент отправляет полезную нагрузку 70 тыс.

Теперь первое замечание, которое я заметил, состоит в том, что если я прохожу через строку кода по строке, инициированной точкой останова, она будет работать нормально, я получаю то же самое количество в исходящем байте []. При свободном запуске байт [] будет иметь разные размеры каждый раз, когда я запускаю код с практически одинаковой полезной нагрузкой.

Сроки проблемы?

Второе наблюдение заключается в том, что, когда размер «inbuffer» установлен на 4096, например, это нечетное поведение происходит. установка размера «inbuffer» на 1 дает правильное поведение, то есть я получаю правильный размер полезной нагрузки.

, пожалуйста, поймите, мне не нравится, как ive пришлось заставить это работать, и я не доволен решением.

Какие впечатления, проблемы у вас были/видели соответственно, которые могут помочь мне исправить этот код, чтобы быть более надежным, более легким для чтения.

public void listenForResponses() { 
    isActive = true; 
    try { 
     // apprently read() doesnt return -1 on socket based streams 
     // if big stuff comes through, TCP packets are segmented, but the inputstream 
     // does something odd and doesnt return the correct raw data. 
     // this is a work around to accept vari-length payloads into one byte[] buffer 
     byte[] inBuffer = new byte[1]; 
     byte[] buffer = null; 
     int bytesRead = 0; 

     byte[] finalbuffer = new byte[0]; 

     boolean isMultichunk = false; 

     InputStream istrm = currentSession.getInputStream(); 

     while ((bytesRead = istrm.read(inBuffer)) > -1 && isActive) { 
      buffer = new byte[bytesRead]; 
      buffer = Arrays.copyOfRange(inBuffer, 0, bytesRead); 

      int available = istrm.available(); 

      if(available < 1) { 
       if(!isMultichunk) { 
        finalbuffer = buffer; 
       } 
       else { 
        finalbuffer = ConcatTools.ByteArrayConcat(finalbuffer,buffer); 
       } 
       notifyOfResponse(deserializePayload(finalbuffer)); 
       finalbuffer = new byte[0]; 
       isMultichunk = false; 
      } 
      else { 
       if(!isMultichunk) { 
        isMultichunk = true; 
        finalbuffer = new byte[0]; 
       } 
       finalbuffer = ConcatTools.ByteArrayConcat(finalbuffer,buffer); 
      } 

     } 
    } catch (IOException e) { 
     Logger.consoleOut("PayloadReadThread: " + e.getMessage()); 
     currentSession = null; 
    } 
} 
+0

Пожалуйста, разместите свой код с буфером размера обычного размера. Затем расскажите, что вы получаете. – greenapps

ответ

0

InputStream работает как запроектированный.

Если я прохожу через строку кода, начинающуюся с точки прерывания, она будет работать нормально, я получаю то же самое количество в исходящем байте [].

Это потому, что переход через код происходит медленнее, поэтому больше данных между считываниями достаточно, чтобы заполнить ваш буфер.

При свободном запуске байт [] будет иметь разные размеры каждый раз, когда я запускаю код с практически одинаковой полезной нагрузкой.

Это потому, что InputStream.read() сжимается до блокировки, пока не был передан хотя бы один байт, или EOS или исключение. См. Javadoc. Там нет ничего о заполнении буфера.

Второе наблюдение заключается в том, что, когда размер «inbuffer» установлен на 4096, например, это нечетное поведение происходит. установка размера «inbuffer» на 1 дает правильное поведение, то есть я получаю правильный размер полезной нагрузки.

Это правильное поведение в случае 1-байтового буфера по той же причине, что указано выше. Это не «правильное поведение» для любого другого размера.

NB Ваш цикл копирования - это нонсенс. availavle() имеет мало правильных применений, и это не один из них.

while ((count = in.read(buffer)) > 0) 
{ 
    out.write(buffer, 0, count); 
} 

NB (2) read() действительно возвращает -1 при сокетов на основе потоков, но только тогда, когда имеет равный или выключение закрыл соединение.