I am currently creating a service allowing to send objects from a client to a server and vice-versa, but experiencing an issue that I unfortunately cannot explain and fix.
First of all, here are the useful classes (I haven't put all methods such as getters and setters in this post).
/**
* This launcher creates a NetworkInterface, waits for a connection, sends a message to the connected client and waits for an incoming message
*
*/
public class ServerLauncher {
public static void main(String[] args) {
try {
NetworkSystem n = new NetworkSystem(4096);
n.startServerManager();
while (n.getCommunications().isEmpty()) {
// this line is unexpectedly magic
System.out.println("Waiting for a new connection...");
}
do {
n.getCommunications().get(0).send(new String("Hello, are you available?"));
} while (n.getCommunications().get(0).getReceiveManager().getReadObjects().isEmpty());
System.out.println(n.getCommunications().get(0).getReceiveManager().getReadObjects().get(0));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* This launcher creates a NetworkSystem, connects to the server, waits for an incoming message and anwers back
*
*/
public class ClientLauncher {
public static void main(String[] args) {
try {
NetworkSystem n = new NetworkSystem(8192);
n.instanciateCommunication(new Socket(InetAddress.getLocalHost(), 4096));
while (n.getCommunications().get(0).getReceiveManager().getReadObjects().isEmpty()) {
// this line is unexpectedly magic
System.out.println("Waiting for an object...");
}
System.out.println(n.getCommunications().get(0).getReceiveManager().getReadObjects().get(0));
n.getCommunications().get(0).getSendManager().send(new String("No, I am not! We will talk later..."));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* This class handles every incoming messages.
*/
public class ReceiveManager implements Runnable {
private ObjectInputStream inputStream;
private CommunicationManager communicationManager;
private List readObjects;
private boolean receive;
public ReceiveManager(CommunicationManager communicationManager) throws IOException {
this.communicationManager = communicationManager;
this.inputStream = new ObjectInputStream(this.communicationManager.getSocket().getInputStream());
this.readObjects = new ArrayList();
this.receive = true;
}
@Override
public void run() {
Object object = null;
try {
while ((object = this.inputStream.readObject()) != null && this.hasToReceive()) {
this.readObjects.add(object);
}
} catch (ClassNotFoundException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
this.setContinueToReceive(false);
}
}
private boolean hasToReceive() {
return this.receive;
}
public void setContinueToReceive(boolean value) {
this.receive = value;
}
}
/**
* This class allows the user to send messages
*/
public class SendManager {
private ObjectOutputStream outputStream;
private CommunicationManager communicationManager;
public SendManager(CommunicationManager communicationManager) throws IOException {
this.communicationManager = communicationManager;
this.outputStream = new ObjectOutputStream(this.communicationManager.getSocket().getOutputStream());
}
public void send(Object object) throws IOException {
this.outputStream.writeObject(object);
this.outputStream.flush();
}
}
So basically, as you may have noticed in the ServerLauncher and the ClientLauncher, there are two "magic" instructions. When those two lines are commented and I run the server then the client, nothing happens. The server and the client are simply running and never stop. However, when I uncomment these two magic lines, every works like a charm: messages are properly sent and received.
Would you guys know the reason of this unexpected behaviour ?
Oh yeah, I forgot, if you guys want me to upload everything to test the project or whatever, just tell me :-)
You're starving the CPU with those spin loops. You should sleep or wait while the queues are empty, or better still just
take()
from blocking queues.NB Your loop condition isn't correct:
readObject()
doesn't returnnull
at end of stream. It throwsEOFException
.hasToReceive()
before callingreadObject()
rather than afterwards. Otherwise you always do an extra read.