I am working on a Java application that communicates via UDP to a server. This is a specific server, in that all it does is relay message" from one client to another, across a network, with a VERY specific message format. The message format is small and compact to make use of an extremely small bandwidth. There are unique rules for this server:
At startup, I send this server an empty service subscription, just to get onto its list of subscribers (which is correct according to the server rules).
After that initial message, I start sending my heartbeats, once every 5 seconds (which is correct according to the server rules).
At this point, I launch a thread to listen for messages from the server.
Finally, I send a subscription request to the server for the services I would like to receive messages about.
It is at this point that I am having problems. If my application is started before the server application is running or if the server application is restarted while my application is running, I don't get any messages from the server.
I think the reason for this is because my listener thread is blocking, waiting for messages that will never come. If I start my application first, my request for services goes out, but the server never receives the request. I then start listening, but the server will never talk to me because (according to the server) I haven't subscribed. I cannot send a subscription request constantly, or the server will disconnect me. The server documentation says, that if two server heartbeats are missed, then a client should re-subscribe. However, I cannot wrap my head around how to do this. Here is what I have. I have indicated where I believe the "trouble" is with the comment "Here is where my listener is blocking, waiting for messages from the server.".
Main
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;
}
}
So, any suggestions on how I can get around this?
Thanks!
myDatagramSocket.receive(myDatagramPacket);
From the docs:
This method blocks until a datagram is received.
If you never register at the server, you are not going to recieve messages and the thread keeps on blocking.
Implementing a timeout on clientside would enable you to keep track of failed registration attempts, for example via
setSoTimeout
Also, you may want to set run = false; after breaking you while loop, since you are not listening anymore at this point.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.