-3

我正在将 C++ 客户端更改为 Java 版本——这只是我尝试的一个练习。

原始的 C++ 代码运行良好。Servce 端发送一个 DWORD,然后客户端查找它,然后读取 253 字节的数据。我已经在 J​​ava 中尝试过,但没有取得很大成功,客户端丢弃了大量数据包〜 20 分之 1 的数据包通过。下面是我尝试过的几个不同的代码块。如果有人能告诉我什么时候出错,我将不胜感激。

谢谢

标记

尝试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);
    }
4

3 回答 3

2

在“尝试 1”中,您正在打印numberRead,而不是totalCharsRead. 这numberRead是在最后一次操作中读取的字符数,而不是缓冲区中的总数。你可以通过尽可能地限制局部变量的范围来避免这个错误,而不是过早地用虚拟值初始化它们。这也使您的代码更具可读性。

使用 TCP,数据包不会在 Java 级别被无声地“丢弃”。这会在操作系统级别或更低级别发生。Java 运行时中的任何问题都会引发异常。

于 2011-06-28T22:28:11.477 回答
0

如果发件人正在发送二进制数据,那么您首先使用 Reader 查找错误的树。使用 DataInputStream.readInt() 读取 DWORD,然后使用 DataInputStream.readFully() 读取数据。并扔掉所有可怕的循环/计数代码。

于 2011-06-29T03:15:13.300 回答
0

我试过你的代码 - 大大降低了 fp!结果还是一样。我已经尝试使用 readInt() 并仅读取 257 字节(总 inc 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,

于 2011-06-29T10:23:00.690 回答