2011-06-28 110 views
-3

我正在将C++客户端更改为Java版本 - 仅仅是一个练习,我正在尝试比其他更多的任务。使用Java客户端读取TCP时丢失/丢失数据包

原始C++代码完美地工作。 Servce端发送一个DWORD,然后客户端查找它,然后读取253个字节的数据。我已经在Java中尝试了这个,取得了很大的成功,客户端丢弃了大量的数据包,大约有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); 
    } 
+1

你是什么意思**客户端丢失大量的数据包**?您是否在监视网络流量,并看到实际的数据包被丢弃?或者你的意思是只读了20个字节中的一个?这两个问题是完全分开的,前者可能与硬件有关(或与连接有关),后者可能是代码中的一个错误。 – SRM

回答

0

我试过你的代码 - 大大减少了fp!仍然是同样的结果。我用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,91,56,12,88,64,2 ,

32-61缺失/未

ÿþÿ,253,62,26129105,94%,65,67,31,23,2,9,5,57,11,88,64读取2,

63-91缺失/未

ÿþÿ,253,92,26129105,94%,65,67,31,23,2,9,5,57,12,88,64读取2,

+0

好吧修好了。上面所有的代码选项都可以工作(Phew!) - 是一个协议错误。卫生署!感谢您的建议,但。 – Mark

2

在 “尝试1”,您打印numberRead,不totalCharsReadnumberRead是最后一次操作读取的字符数,而不是缓冲区中的总数。您可以尽可能地限制本地变量的范围,避免过早使用虚拟值对它们进行初始化,从而避免此错误。这使得你的代码更具可读性。

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

+0

感谢您的回复。 Re:打印的数据项数量 - 只是一些调试,我的错误。基本上这些数据是从服务器流出的。使用C++客户端,我可以正确接收所有数据包。 Java中只有20个左右出现约1个。 – Mark

+0

@Mark - 在这两种情况下都不清楚你如何确定你读过多少字节。第一,你有一个错误,第二,你没有总结他们,你不提供任何版本的示例输出。 Java不会丢弃你的数据包;该错误在您的代码中。因此,不要将其视为理由,*展示*不是:发布您的实际代码及其结果。 – erickson

0

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