Java数据报发送和接收不同步
我有一个使用UDP数据报回复命令的设备。我正试图想出一种方法来保证响应来自某个特定的请求。当我运行下面的代码时,我得到前两个,有时是第三个请求,然后它只是挂起并超时接收。我尝试了几种不同的方法来解决这个问题(因此出现了同步和iqueueinter接收超时)。以下是一个跑步示例: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
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
,或者至少在每次读取循环时重置其长度:否则它可能会一直缩小到目前为止接收到的最小数据报的大小