java BufferedReader определенная длина возвращает NUL символов - PullRequest
0 голосов
/ 22 апреля 2010

У меня есть клиент сокета TCP, получающий сообщения (данные) с сервера. сообщения имеют тип длины (2 байта) + данные (длина байта), разделенные символами STX и ETX.

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

Большую часть времени у меня нет проблем, но НЕКОТОРЫЕ (1 из тысяч полученных сообщений), когда я пытаюсь прочитать (длину) байтов от читателя, я получаю только часть этого, остальная часть моего массива заполнены символами "NUL". Я полагаю, это потому, что буфер еще не заполнен.

char[] bufLen = new char[2];
_bufferedReader.read(bufLen);

int len = decodeLength(bufLen);

char[] _rawMsg = new char[len];
_bufferedReader.read(_rawMsg);

return _rawMsg;

Я решил проблему несколькими итерационными способами:

  • сначала я проверил последний символ моего массива: если бы это был не ETX, я бы считывал символы из bufferedReader один за другим, пока не достигнул бы ETX, а затем начал с обычной процедуры. Следствием этого является то, что я в основном УДАЛУ одно сообщение.

  • затем, чтобы по-прежнему получить это сообщение, я обнаружил первый случай появления символа NUL в моем «усеченном» сообщении, прочитал и сохранил дополнительные символы по одному, пока я не достиг ETX, и добавил их на мои "усеченные" сообщения, подтверждающие длину в порядке.

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

любая идея / указатель?

спасибо!

Ответы [ 2 ]

2 голосов
/ 22 апреля 2010

Метод чтения InputStream может возвращать короткие чтения; Вы должны проверить возвращаемое значение, чтобы определить, сколько символов было прочитано, и продолжить чтение в цикле, пока не получите желаемое число. Метод может блокироваться, но он блокируется только до тех пор, пока не будут доступны некоторые данные, необязательно все запрошенные вами данные.

Большинство людей заканчивают тем, что пишут метод readFully, такой как DataInputStream, который читает ожидаемый объем данных или генерирует IOException:

static public int readFully(InputStream inp, byte[] arr, int ofs, int len) throws IOException {
    int                                 rmn,cnt;

    for(rmn=len; rmn>0; ofs+=cnt, rmn-=cnt) {
        if((cnt=inp.read(arr,ofs,rmn))==-1) { 
            throw new IOException("End of stream encountered before reading at least "+len+" bytes from input stream"); 
            }
        }
    return len;
    }
1 голос
/ 22 апреля 2010

Вот пример сервера, который я использовал для тестирования Основной RCV структурирован как

while((chars_read = from_server.read(buffer)) != -1)
{
    to_user.write(buffer,0,chars_read);
    to_user.flush();
}

Фактический весь сервер ниже ...

   public static void main(String[] args) throws IOException
   {
      try
      {
         if (args.length != 2)
            throw new IllegalArgumentException("Wrong number of Args");

         String   host = args[0];
         int      port = Integer.parseInt(args[1]);

         Socket   s = new Socket(host,port);

         final Reader from_server = new InputStreamReader(s.getInputStream());
         PrintWriter to_server = new PrintWriter(new OutputStreamWriter(s.getOutputStream()));

         BufferedReader from_user = new BufferedReader(new InputStreamReader(System.in));
         final PrintWriter to_user = new PrintWriter(new OutputStreamWriter(System.out));

         to_user.println("Connected to " + s.getInetAddress() + ":" + s.getPort());

         Thread t = new Thread()
         {
            public void run()
            {
               char [] buffer = new char[1024];
               int chars_read;
               try
               {
                  while((chars_read = from_server.read(buffer)) != -1)
                  {
                     to_user.write(buffer,0,chars_read);
                     to_user.flush();
                  }
               }
               catch(IOException e)
               {
                  to_user.println(e);
               }

               to_user.println("Connection closed by server");
               to_user.flush();
               System.exit(0);
            }
         };

         t.setPriority(Thread.currentThread().getPriority() + 1);
         t.start();

         String line;
         while ((line = from_user.readLine()) != null)
         {
            to_server.println(line);
            to_server.flush();
         }

         //t.stop();
         s.close();
         to_user.println("Connection closed by client");
         to_user.flush();
      }
      catch(Throwable e)
      {
         e.printStackTrace();
         System.err.println("Usage : java TCPClient <hostname> <port>");
      }
   }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...