-3

I'm changing a C++ client to a Java version - just an exercise I'm trying more than anything else.

The orginal C++ code works perfectly well. The Servce side sends a DWORD then the client looks for this then reads the 253 bytes of data. I've tried this in Java with out much success, the client is dropping lots of packets ~ 1 in 20 come through. Below are a couple of different code blocks I've tried. If anyone can tell me when I'm going wrong I'm most appreciate it.

Thanks

Mark

Attempt 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);
    }

Attempt 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);
    }
Mark
  • 3
  • 2
  • 1
    what do you mean by ** the client is dropping lots of packets **? Are you monitoring the network traffic and you see actual packets being dropped? Or do you mean that only one out of 20 bytes are read? The two problems are completely separate with the former probably being hardware related (or connection related) and the latter is probably a bug in your code. – SRM Jun 28 '11 at 22:25

3 Answers3

2

In "Attempt 1", you are printing numberRead, not totalCharsRead. The numberRead is the number characters read on the last operation, not the total in the buffer. You could avoid this bug by limiting the scope of your local variables as much as possible, and not prematurely initializing them with dummy values. This makes your code more readable as well.

With TCP, packets won't be "dropped" silently at the Java level. That's something that would happen at the OS level, or below. Any problems in the Java runtime would raise an exception.

erickson
  • 265,237
  • 58
  • 395
  • 493
  • Thanks for the reply. Re: the number of data items printed out - just some debug, my mistake. Basically this data is streamed out from the server. Using the C++ client I receive all the packets correctly. The Java one only show up about 1 in 20 or so. – Mark Jun 28 '11 at 22:32
  • @Mark - It's not clear in either case how you are determining how many bytes you've read. In the first, you have a bug, and in the second, you don't sum them, and you don't provide sample output for either version. Java is not dropping your packets; the bug is in your code. So, rather than dismissing that as the reason, *demonstrate* that is is not: post your actual code and its results. – erickson Jun 28 '11 at 22:38
0

If the sender is sending binary data you are barking up the wrong tree with a Reader in the first place. Use DataInputStream.readInt() to read the DWORD, then DataInputStream.readFully() to read the data. And throw all that terrible looping/counting code away.

user207421
  • 305,947
  • 44
  • 307
  • 483
0

I've tried your code - much reduced the fp! Still the same result. I've tried with both readInt() and just reading 257 bytes (total inc DWORD) Looking at the data it's almost always missing 30/31 packets of data - suspisious!!. Code below:

         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();
    }

Example Data (It is binary, the third column is the packet seq id - can't show all of it as some is non printing char's thus shown here is only a part of the data. But I am seeing the whole lot come through when it reads a packet)

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

32-61 missing/not read in

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

63-91 missing/not read in

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

Mark
  • 16
  • 1
  • 1
  • Okay fixed it. All the code options above work (Phew!) - was a protocol error. Doh!. Thanks for the advice though. – Mark Jun 29 '11 at 14:11