我正在将C ++客户端更改为Java版本 - 这只是我正在尝试的一项练习。
原始C ++代码非常有效。 Servce端发送一个DWORD然后客户端查找它然后读取253个字节的数据。我已经在Java中尝试了这个并取得了很大的成功,客户端正在丢弃大量的数据包~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);
}
答案 0 :(得分:2)
在“尝试1”中,您正在打印numberRead
,而不是totalCharsRead
。 numberRead
是上次操作中读取的数字字符,而不是缓冲区中的总数。您可以通过尽可能地限制局部变量的范围来避免此错误,而不是过早地使用虚拟值初始化它们。这使得您的代码也更具可读性。
使用TCP,数据包不会在Java级别静默“丢弃”。这是在OS级别或更低级别发生的事情。 Java运行时中的任何问题都会引发异常。
答案 1 :(得分:0)
如果发件人正在发送二进制数据,那么您首先会使用Reader咆哮错误的树。使用DataInputStream.readInt()读取DWORD,然后使用DataInputStream.readFully()读取数据。抛弃所有可怕的循环/计数代码。
答案 2 :(得分: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 - 无法显示所有内容,因为有些是非打印字符,因此这里显示的只是数据的一部分。但我看到了整个当它读取数据包时会通过)
25,253,31,26,129,105,94,65,67,31,23,2,9,791,56,12,88,64,2,
32-61缺失/未读
25,253,62,26,129,105,94,65,67,31,23,2,9,5,57,11,88,64,2,
63-91缺少/未读
25,253,92,26,129,105,94,65,67,31,23,2,9,5,57,12,88,64,2,