Отсутствие / удаление пакетов при использовании Java-клиента для чтения по TCP - PullRequest
0 голосов
/ 29 июня 2011

Я меняю клиент 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 ]

2 голосов
/ 29 июня 2011

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

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

0 голосов
/ 29 июня 2011

Я пробовал твой код - сильно уменьшил фп! Все тот же результат. Я пробовал как с 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,

0 голосов
/ 29 июня 2011

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

...