Java 我的UDP客户端应用程序逻辑有问题
我正在开发一个通过UDP与服务器通信的Java应用程序。这是一个特定的服务器,因为它所做的只是通过网络将“消息”从一个客户机中继到另一个客户机,消息格式为非常特定的消息格式。消息格式小且紧凑,可利用极小的带宽。此服务器有独特的规则:Java 我的UDP客户端应用程序逻辑有问题,java,multithreading,udp,Java,Multithreading,Udp,我正在开发一个通过UDP与服务器通信的Java应用程序。这是一个特定的服务器,因为它所做的只是通过网络将“消息”从一个客户机中继到另一个客户机,消息格式为非常特定的消息格式。消息格式小且紧凑,可利用极小的带宽。此服务器有独特的规则: 服务器只接受特定消息格式的UDP数据报 服务器是基于订阅的。仅当客户端订阅了特定的消息协议(如聊天、时间、温度、频道等)时,服务器才会发送客户端消息 订阅服务时,必须向服务器发送一个永久UDP侦听端口,以便服务器可以向您发送订阅的邮件。如果您不在该端口上侦听,则无法
public static void main(String[] args){
SubscribeToServices mySubscriptions = new SubscribeToServices();
mySubscriptions.subscribe(0); // 0 means no services
Heartbeat myHeartbeat = new Heartbeat();
Thread heartbeatThread = new Thread(myHeartbeat);
heartbeatThread.start();
MyListener listener = new MyListener();
Thread listenerThread = new Thread(listener);
listenerThread.start();
mySubscriptions.subscribe(1234); // a specific set of subscriptions
}
MyListener.java
public class MyListener implements Runnable {
private static final Logger LOG = Logger.getLogger(MyListener.class.getName());
private volatile boolean run = true;
private DatagramSocket myDatagramSocket;
private DatagramPacket myDatagramPacket;
private MessageHeader messageHeader;
private int receiveBufferSize;
private byte[] receiveBuffer;
private int messageID;
private Timer myTimer;
@Override
public void run() {
try {
// Create and bind a new DatagramSocket
myDatagramSocket = new DatagramSocket(null);
InetSocketAddress myInetSocketAddress = new InetSocketAddress(15347);
myDatagramSocket.bind(myInetSocketAddress);
} catch (SocketException se) {
LOG.log(Level.SEVERE, se.getMessage());
return;
}
// Set-up the receive buffer
receiveBuffer = new byte[2047];
myDatagramPacket = new DatagramPacket(receiveBuffer, 2047);
while (run) {
try {
// Receive the data from Server
// Here is where my listener is blocking, waiting for messages from the server.
myDatagramSocket.receive(myDatagramPacket);
} catch (IOException ioe) {
LOG.log(Level.SEVERE, ioe.getMessage());
break;
}
byte[] data = myDatagramPacket.getData();
receiveBufferSize = myDatagramPacket.getLength();
// Extract the message header and ID
messageHeader = ExtractMessageHeaders.extract(data, receiveBufferSize);
messageID = (messageHeader.getMessageID() & 0xff);
switch (messageID) {
// Do switch here ...
// Check for the heartbeat and other messages from the server.
}
myDatagramPacket.setLength(2047);
}
}
public boolean isRun() {
return run;
}
public void setRun(boolean run) {
LOG.log(Level.INFO, "Changing the listening thread.");
this.run = run;
}
}
那么,有什么建议可以帮助我解决这个问题吗
谢谢
myDatagramSocket.receive(myDatagramPacket);
从文档中:
此方法会一直阻塞,直到收到数据报为止
如果您从未在服务器上注册,您将不会收到消息,线程将继续阻塞
在客户端实现超时将使您能够跟踪失败的注册尝试,例如通过
设置超时
此外,您可能需要设置run=false中断while循环后,因为此时您不再收听。UDP不可靠,所以我会分散订阅,但遵守服务器的防洪泛规则。这意味着我将在短时间内发送5个订阅,然后等待看是否从服务器得到答案,如果没有,然后扇出4在一个更宽的距离,然后3然后2然后1,然后我考虑服务器下来,放弃通知用户或处理这种情况,否则。一个问题:你对丢失的心跳有反应吗?你真的重新订阅了吗?不,我对丢失的心跳或重新订阅没有反应。我不知道我会/应该在哪里做这件事。你需要启动一个“heartbeatlistener”线程,它只监视来自服务器的心跳信号,并提供一种发出服务器中断信号的方法。您编写协议sais 2连续丢失的心跳将触发重新订阅。因此,您可以在监视器上注册某种监听器,当发生这种情况时,监听器将被通知(执行)。您可能需要实现“下侧翼触发”。也就是说,当心跳到达时,服务器将启动和运行,当两个时间帧没有心跳时,信号“服务器宕机”。什么使您认为IOExt会被抛出?因为这是监听传入消息的方式。如果服务器正在发送,但没有收到任何消息,则Receive未被执行。是。它会阻塞。但也不例外。在这里,阻塞是预期的行为,将导致正确接收消息。从OP提供的信息来看,就我所知,这是唯一一种不接收消息的方式。我删除了“中断”,但它仍然卡在同一个位置。