我有一个运行统一C#应用程序的PC,它每隔几毫秒通过网络向其他机器发送一个UDP数据包( windows 7上有两个KUKA机器人,运行相同的JAVA程序,它有一个i5 Intel处理器,所以非常强大)。Java程序应该接收这些包,解析它们的内容(机器人的位置,用由‘#’分隔的7个值组成的数组编码),然后再移动和读取。问题是,当PC以每0.02秒1次的速率发送数据包(这不是在0.03或0.03以上,这是硬件限制?!),java程序会冻结在收到的大约1000个数据包(有时是955或986,等等)。持续8-10秒,然后再继续。当它到达2000年和3000的时候,它也会这样做。
该方案冻结在:
serverSocket.receive(receivedPacket); // receives the array of Bytes我怀疑网络开关,所以把PC直接连接到机器人上,但没有什么改变。奇怪的是,这两个机器人同时发生,这让我怀疑PC。但是,当我的同事启动一个控制台,实时显示发送数据包的C#程序时,当java程序被冻结时,它并没有冻结,看起来这些数据包丢失了。
我在SO上寻找类似的问题,很多可疑的缓冲区,所以我正在考虑创建一个线程,该线程侦听UDP端口并将数据包存储在内存中的队列中,然后我的主要java程序从该线程读取。这看上去像是一个可行的轨道吗?欢迎任何建议。
这是密码:
package readers;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MyProgram {
// Network variables
public static DatagramSocket serverSocket;
private static DatagramPacket receivedPacket;
// Received data variables
private static byte[] aReceivedData = new byte[1024];
private static String sReceivedData;
private static String sAxesInformationReceived;
private static Double[] dAxesInformationReceived = new Double[7];
// ******** MAIN ***************************************
public static void main(String[] args) throws Exception {
int mFramecount =0;
int mPort = 30004; //default value
int mTimeout = 20*1000; //default value
int mFramelimit = (15 * 1000); //default value
// Create UDP server socket
try {
serverSocket = new DatagramSocket(mPort);
serverSocket.setReuseAddress(true);
serverSocket.setSoTimeout(mTimeout);
} catch (SocketException e)
{ System.err.println("socket bind fail"); closeSocket();e.printStackTrace(); return; }
// Receive the UDP packet
try {
receivedPacket = new DatagramPacket(aReceivedData, aReceivedData.length);
serverSocket.receive(receivedPacket); // receive the array of Bytes
} catch (Exception e) { closeSocket(); return; }
//Clear Buffer
for (int i = 0; i < 7; i++) {
if(dAxesInformationReceived[i] == null)
{
dAxesInformationReceived[i] = 0.0;
}
}
// <<<<<<<<<<<WHILE <<<<<<<<<<<<<<<<<<<<
while (true) {
//Clear Buffer
for(int i=0; i < aReceivedData.length; i++)
{
aReceivedData[i]=0;
}
// Decoding and Parsing received values
try {
receivedPacket = new DatagramPacket(aReceivedData, aReceivedData.length);
serverSocket.receive(receivedPacket); // receive the array of Bytes
byte[] byteData = new byte[receivedPacket.getLength()];
System.arraycopy(receivedPacket.getData(), receivedPacket.getOffset(), byteData, 0, receivedPacket.getLength());
sReceivedData = new String(byteData, "UTF-8");
Pattern pattern = Pattern.compile("@(.*?)@"); // RegEx
Matcher matcher = pattern.matcher(sReceivedData);
System.out.println("Data: '" + sReceivedData + "', || length: " + byteData.length + "|| Frame count="+ mFramecount ++);
/*
* mFramecount++;
if (mFramecount %100 == 0) {
System.out.println("Data: '" + sReceivedData + "', || length: " + byteData.length + "|| Frame count="+ mFramecount );
}
*/
if (matcher.find()) {
sAxesInformationReceived = matcher.group(1);
String[] sAxesValuesInStringArray = sAxesInformationReceived.split("#");
if (sAxesValuesInStringArray.length != 7) {
System.err.println("[UnityControl] invalide number of axis");
break;
}
for (int i = 0; i < 7; i++) {
dAxesInformationReceived[i] = Double.parseDouble(sAxesValuesInStringArray[i]);
}
} else {
System.err.println("[UnityControl] invalid format");
break;
}
} catch (Exception e) {
System.err.println("[UnityControl] socket exception");
e.printStackTrace();
break;
}
/* THIS PART IS USING THE ROBOT's API */
// Change destination according to the received position
JointPosition framePos = new JointPosition(
Math.toRadians(dAxesInformationReceived[0]),
Math.toRadians(dAxesInformationReceived[1]),
Math.toRadians(dAxesInformationReceived[2]),
Math.toRadians(dAxesInformationReceived[3]),
Math.toRadians(dAxesInformationReceived[4]),
Math.toRadians(dAxesInformationReceived[5]),
Math.toRadians(dAxesInformationReceived[6]));
try {
if(runtime.setDestination(framePos)<0)
break; // break when error planning robot motion
}
catch(Exception e)
{
System.err.println("Runtime exeption");
break;
}
if(mFramecount >= mFramelimit) break;
}
// LOOP BACK
}
//**********************************************************************
static void closeSocket() {
if (serverSocket != null) {
serverSocket.disconnect();
serverSocket.close();
System.out.println("[UnityControl] socket closed");
}
}
}

我做了@EJP在他的回答中提出的建议,为了更好地跟踪问题,我在它的末尾添加了数据包的数量,看起来这两台机器上的UDP数据包都丢失了(PC的日志显示它没有停止发送)。下面是运行相同代码的两台机器的日志:

发布于 2017-01-11 16:00:57
很有可能是你的垃圾收集(垃圾收集)的问题,正在制造的东西被称为停止世界。停止这个世界,冻结应用程序,清除未使用对象的内存:)。您可以获得程序PID,然后连接j控制台,查看内存发生了什么变化。
也有可能设置更多的内存将有所帮助。java -Xms1024m -Xmx1024m -Xms设置初始Java堆大小-Xmx设置最大Java堆大小
如果您正在使用许多线程,那么创建线程就有可能是如此的内存和时间消耗--那么您可以使用线程池。
不幸的是,没有任何密码,我无法帮助你更多。
https://stackoverflow.com/questions/41593385
复制相似问题