Отсутствие / удаление пакетов при использовании Java-клиента для чтения по TCP

Я изменяю клиент C++ на версию Java - просто упражнение, которое я пробую больше всего на свете.

Оригинальный код C++ работает на отлично. Сторона Servce отправляет DWORD, затем клиент ищет это, а затем считывает 253 байта данных. Я пробовал это на Java без особого успеха, клиент сбрасывает много пакетов, ~ 1 из 20 проходит. Ниже приведены несколько разных блоков кода, которые я пробовал. Если кто-то может сказать мне, когда я иду не так, я очень ценю это.

Спасибо

отметка

Попытка 1:

        //Create socket connection
    try
    {
        client = new Socket("localhost", 7651);
        //in = client.getInputStream();
        reader = new BufferedReader(new
                InputStreamReader(client.getInputStream(), "ISO-8859-1"));
    } 
    catch (UnknownHostException e) 
    {
        System.out.println("Unknown host: localhost");
        System.exit(1);
    } 
    catch  (IOException e) 
    {
        System.out.println("No I/O");
        System.exit(1);
    }

    //Receive data from ROS SerialtoNetwork server

    while (true)
    {
        // Read repeatedly until the expected number of chars has been read:
        char[] buf = new char[300];
        int numberRead = 0;

        int numberToRead = 257;
        for (int totalCharsRead = 0; totalCharsRead < numberToRead; ) 
        {
            int numberLeft = numberToRead - totalCharsRead;

            try {
                numberRead = reader.read(buf, totalCharsRead, numberLeft);

                if (numberRead < 0) 
                {
                    // premature end of data
                    break;
                } 
                else 
                {
                    totalCharsRead += numberRead;
                }               
            } 
            catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        String lstr = new String(buf);
        System.out.print(lstr);

        System.out.println("");
        System.out.println("Bytes Received:" + numberRead);
    }

Попытка 2:

        //Create socket connection
    try
    {
        client = new Socket("localhost", 7651);
        in = client.getInputStream();           
    } 
    catch (UnknownHostException e) 
    {
        System.out.println("Unknown host: localhost");
        System.exit(1);
    } 
    catch  (IOException e) 
    {
        System.out.println("No I/O");
        System.exit(1);
    }

    //Receive data from ROS SerialtoNetwork server

    try
    {
        while (true)
        {
            byte[] cbuf = new byte[300];
            int lBytesAvail = in.available();//read(cbuf, 0, 4);

            if (lBytesAvail > 253)
            {
                in.read(cbuf, 0, 4);
                int lBytesRead = in.read(cbuf, 0, 253);

                String lstr = new String(cbuf);
                System.out.print(lstr);

                System.out.println("");
                System.out.println("Bytes Received:" + lBytesRead);
            }

        }
    } 
    catch (IOException e)
    {
        System.out.println("Read failed");
        System.exit(1);
    }

3 ответа

Решение

Я пробовал твой код - сильно уменьшил фп! Все тот же результат. Я пробовал как с readInt(), так и с чтением 257 байт (всего с учетом DWORD). Глядя на данные, почти всегда отсутствует 30/31 пакетов данных - подозрительно!! Код ниже:

         try
     {
         lSocket = new Socket("localhost", 7651);
         lDataStream = new DataInputStream(lSocket.getInputStream());

     }
     catch (UnknownHostException e)
     {
         System.out.println("Unknown host: localhost");
         System.exit(1);
     }
     catch  (IOException e)
     {
         System.out.println("No I/O");
         System.exit(1);
     }

     //Receive data from ROS SerialtoNetwork server

     try 
     {
         while(true)
         {
            //in.readInt();
            byte[] cbuf = new byte[257];
            lDataStream.readFully(cbuf);        

            String lstr = new String(cbuf);
            System.out.print(lstr);

            System.out.println("");
         }            
    } 
    catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

Пример данных (это двоичный файл, третий столбец - это seq id пакета - не могу показать все это, так как некоторые из них не являются печатными символами, поэтому здесь показана только часть данных. Но я вижу, что вся партия проходит через это читает пакет)

ÿþÿ, 253, 31, 26,129,105, 94, 65, 67, 31, 23, 2, 9,791, 56, 12, 88, 64, 2,

32-61 отсутствует / не читается в

ÿþÿ, 253, 62, 26,129,105, 94, 65, 67, 31, 23, 2, 9, 5, 57, 11, 88, 64, 2,

63-91 отсутствует / не читается в

ÿþÿ,253, 92, 26,129,105, 94, 65, 67, 31, 23, 2, 9, 5, 57, 12, 88, 64, 2,

В "Попытка 1" вы печатаете numberReadне totalCharsRead, numberRead число символов, прочитанных в последней операции, а не сумма в буфере. Вы можете избежать этой ошибки, максимально ограничив область действия локальных переменных, и не преждевременно инициализируя их фиктивными значениями. Это делает ваш код более читабельным.

С TCP пакеты не будут "отброшены" без вывода сообщений на уровне Java. Это то, что произойдет на уровне ОС или ниже. Любые проблемы во время выполнения Java вызовут исключение.

Если отправитель отправляет двоичные данные, вы в первую очередь создаете неправильное дерево, читателем. Используйте DataInputStream.readInt() для чтения DWORD, затем DataInputStream.readFully() для чтения данных. И выбросить весь этот ужасный код зацикливания / подсчета.

Другие вопросы по тегам