我有一个与UDP服务器通信的应用程序。我的应用程序侦听一个端口(比如1234)并发送另一个端口(比如5678)。我正在与之通信的UDP服务器也需要5秒钟的“心跳”,我为此创建了另一个线程。当我的应用程序首次启动时,我创建了监听线程,然后创建心跳线程,然后我开始发送UDP服务器消息包。但唯一的一点是,在心跳线程开始之前,我发出的所有数据包似乎都已完成。
以下是我对听众的看法:
public class MyListener implements Runnable {
private volatile boolean run = true;
private DatagramSocket myDatagramSocket;
private DatagramPacket myDatagramPacket;
private byte[] receiveBuffer;
private int receiveBufferSize;
@Override
public void run(){
while(run){
try {
myDatagramSocket = new DatagramSocket(null);
InetSocketAddress myInetSocketAddress = new InetSocketAddress(1234);
myDatagramSocket.bind(myInetSocketAddress);
receiveBuffer = new byte[2047];
myDatagramPacket = new DatagramPacket(receiveBuffer, 2047);
myDatagramSocket.receive(myDatagramPacket);
byte[] data = myDatagramPacket.getData();
receiveBufferSize = myDatagramPacket.getLength();
switch(messageID){
...
}
} catch (Exception e){
}
}
}
}
这就是我的心跳:
public class MyHeartbeat implements Runnable {
private volatile boolean run = true;
private HeartbeatSenderClass heartbeatSender;
@Override
public void run(){
while(run){
try {
TimeUnit.SECONDS.sleep(5);
heartbeatSender.sendHeartbeat();
} catch(Exception e){
}
}
}
}
以下是我主要课程的内容:
public class MyApp {
public static void main(String[] args){
MyListener listener = new MyListener();
Thread listenerThread = new Thread(listener);
listenerThread.setName("Listener Thread");
listenerThread.start();
MyHeartbeat heartbeat = new MyHeartbeat();
Thread heartbeatThread = new Thread(heartbeat);
heartbeatThread.setName("Heartbeat Thread");
heartbeatThread.start();
MySender sender = new MySender();
Thread senderThread = new Thread(sender);
senderThread.setName("Sender Thread");
senderThread.start();
}
}
我的所有数据包都在进入UDP服务器,但并不像我想象的那样顺利。我会想到,当我向服务器发送数据包时,每5秒我的心跳就会被发送出去。但是,似乎我的心跳只在我的数据包发送完毕后才会出现。另外,我相信我没有从UDP服务器获取所有消息。我这样说是因为我在我的机器上嗅到了UDP数据包,而且我看到来自服务器的数据是我的接收器没有接收/处理的。有什么建议吗?
答案 0 :(得分:1)
你心跳加速:
TimeUnit.SECONDS.sleep(5);
heartbeatSender.sendHeartbeat();
所以在发送第一个节拍之前,你等待5秒钟。难怪其他线程同时完成它们的工作。
答案 1 :(得分:0)
用于发送数据包的DatagramSocket是一个在线程之间竞争的共享资源,然后如果一个线程消耗了太多的资源,另一个可能会饿死。请参阅:Thread starvation
此外,如果您丢失数据包,则会发生这种情况,因为您无法以尽可能快的速度阅读。如果udp数据包到达速度更快,则可以读取它们,队列将丢弃剩余的数据包。
在linux下,您可以使用以下命令控制接收缓冲区:
sudo sysctl -w net.core.rmem_default=26214400
sudo sysctl -w net.ipv4.udp_mem='26214400 26214400 26214400'
sudo sysctl -w net.ipv4.udp_rmem_min=26214400
但无论如何,如果我们谈论持续的损失,你应该考虑让一个线程来读取缓冲区,一个队列和一个线程来处理这些已知的数据。