Java数据报发送和接收不同步

Java数据报发送和接收不同步,java,udp,datagram,Java,Udp,Datagram,我有一个使用UDP数据报回复命令的设备。我正试图想出一种方法来保证响应来自某个特定的请求。当我运行下面的代码时,我得到前两个,有时是第三个请求,然后它只是挂起并超时接收。我尝试了几种不同的方法来解决这个问题(因此出现了同步和iqueueinter接收超时)。以下是一个跑步示例: Listening for X-Air responses Sending X-Air requests Servicing request 6 Send loop - bWait=true request.size=6

我有一个使用UDP数据报回复命令的设备。我正试图想出一种方法来保证响应来自某个特定的请求。当我运行下面的代码时,我得到前两个,有时是第三个请求,然后它只是挂起并超时接收。我尝试了几种不同的方法来解决这个问题(因此出现了同步和iqueueinter接收超时)。以下是一个跑步示例:

Listening for X-Air responses
Sending X-Air requests
Servicing request 6
Send loop - bWait=true request.size=6 iQueuePointer=6
/info,ssssV0.04XR12-24-00-6EXR121.10 from 6
Removed 6
Servicing request 5
Send loop - bWait=true request.size=5 iQueuePointer=5
/ch/01/config/name,sPreach Mic from 5
Removed 5
代码如下:

public static final Object socketLock = new Object();
public static DatagramSocket socket;
public static ArrayList<String> request = new ArrayList<>();
public static int iQueuePointer;
public static boolean bWait;

public static void main(String[] args) {
    new Main();
}

private Main() {

    try {
        socket = new DatagramSocket();
    } catch (SocketException e) {
        e.printStackTrace();
    }
    new Thread(receiveRunnable).start();
    new Thread(sendRunnable).start();
    iQueuePointer++;
    request.add("/info");
    iQueuePointer++;
    request.add("/ch/01/config/name");
    iQueuePointer++;
    request.add("/ch/02/config/name");
    iQueuePointer++;
    request.add("/ch/03/config/name");
    iQueuePointer++;
    request.add("/ch/04/config/name");
    iQueuePointer++;
    request.add("/ch/05/config/name");
    iQueuePointer++;
}

private Runnable sendRunnable = new Runnable() {
    @Override
    public void run() {
        System.out.println("Sending requests");
        while(socket != null) {
            if(!bWait && request.size() > 0 && request.size() < iQueuePointer) {
                iQueuePointer--;
                bWait = true;
                System.out.println("Servicing request " + iQueuePointer);
                //synchronized (socketLock) {
                    try {
                        socket.send(new DatagramPacket(request.get(0).getBytes(),
                                request.get(0).getBytes().length,
                                InetAddress.getByName("192.168.0.180"), 10024));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                //}
            }
        }
        System.out.println("sendRunnable ended");
    }
};

private Runnable receiveRunnable = new Runnable() {

    @Override
    public void run() {
        System.out.println("Listening for responses");
        byte[] data = new byte[1024];
        DatagramPacket packet = new DatagramPacket(data, data.length);
        while(socket != null) {
            //synchronized (socketLock) {
                try {
                    //socket.setSoTimeout(5000);
                    socket.receive(packet);
                    if (packet.getLength() > 0 && socket != null) {
                        System.out.println(new String(Arrays.copyOf(packet.getData(), packet.getLength()))
                                + " from " + iQueuePointer);
                        request.remove(0);
                        System.out.println("Removed " + iQueuePointer);
                        bWait = false;
                    }
                } catch (Exception e) {
                    if (!e.toString().contains("Receive timed out")) {
                        e.printStackTrace();
                    } else {
                        System.out.println("Receive loop - bWait=" + bWait + " request.size=" + request.size()
                                + " iQueuePointer=" + iQueuePointer);
                    }
                }
            //}
        }
        System.out.println("receiveRunnable ended");
    }
};
publicstaticfinalobjectsocketlock=newobject();
公共静态DatagramSocket套接字;
公共静态ArrayList请求=新建ArrayList();
公共静态互联网;
公共静态布尔bWait;
公共静态void main(字符串[]args){
新的Main();
}
专用干管(){
试一试{
套接字=新的DatagramSocket();
}捕获(SocketException e){
e、 printStackTrace();
}
新线程(receiveRunnable).start();
新线程(sendRunnable.start();
iqueuepenter++;
请求。添加(“/info”);
iqueuepenter++;
添加(“/ch/01/config/name”);
iqueuepenter++;
添加(“/ch/02/config/name”);
iqueuepenter++;
添加(“/ch/03/config/name”);
iqueuepenter++;
请求添加(“/ch/04/config/name”);
iqueuepenter++;
添加(“/ch/05/config/name”);
iqueuepenter++;
}
private Runnable sendRunnable=new Runnable(){
@凌驾
公开募捐{
System.out.println(“发送请求”);
while(套接字!=null){
如果(!bWait&&request.size()>0&&request.size(){
伊奎欧冬--;
bWait=真;
System.out.println(“服务请求”+iQueuePointer);
//已同步(socketLock){
试一试{
socket.send(新的DatagramPacket(request.get(0).getBytes(),
request.get(0.getBytes().length,
InetAddress.getByName(“192.168.0.180”),10024);
}捕获(IOE异常){
e、 printStackTrace();
}
//}
}
}
System.out.println(“sendRunnable end”);
}
};
private Runnable ReceiverUnable=新Runnable(){
@凌驾
公开募捐{
System.out.println(“侦听响应”);
字节[]数据=新字节[1024];
DatagramPacket数据包=新的DatagramPacket(数据,数据.长度);
while(套接字!=null){
//已同步(socketLock){
试一试{
//插座。设置插座输出(5000);
套接字接收(数据包);
if(packet.getLength()>0&&socket!=null){
System.out.println(新字符串(Arrays.copyOf(packet.getData(),packet.getLength()))
+“来自”+iqueueponer);
请求。删除(0);
系统输出打印项次(“删除”+iQueuePointer);
bWait=假;
}
}捕获(例外e){
如果(!e.toString()包含(“接收超时”)){
e、 printStackTrace();
}否则{
System.out.println(“接收循环-bWait=“+bWait+”request.size=“+request.size()
+“iQueuePointer=“+iQueuePointer”);
}
}
//}
}
System.out.println(“未命名的接收方”);
}
};

在UDP中,您不能假设响应与请求的发送顺序相同,或者根本不能假设响应只到达一次

您必须在两者中使用序列号来匹配它们,否则就不会有任何挂起的请求,并不断发出请求,直到得到响应,然后您仍然必须以某种方式处理重复的请求

注意:您需要重新创建
DatagramPacket
,或者至少在每次读取循环时重置其长度:否则它可能会一直缩小到目前为止接收到的最小数据报的大小