Receiving objects from server on separate thread

This commit is contained in:
Kai S. K. Engelbart 2019-12-30 18:18:03 +02:00
parent 0efc8dbbc7
commit c06a2e8c37
4 changed files with 88 additions and 16 deletions

View File

@ -1,7 +1,5 @@
package envoy.client;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.util.Map;
import java.util.logging.Logger;
@ -9,6 +7,7 @@ import java.util.logging.Logger;
import envoy.client.util.EnvoyLog;
import envoy.data.LoginCredentials;
import envoy.data.User;
import envoy.exception.EnvoyException;
import envoy.util.SerializationUtils;
/**
@ -23,10 +22,11 @@ import envoy.util.SerializationUtils;
*/
public class Client {
private Socket socket;
private Config config = Config.getInstance();
private User sender, recipient;
private boolean online;
private Socket socket;
private Config config = Config.getInstance();
private volatile User sender;
private User recipient;
private boolean online;
private static final Logger logger = EnvoyLog.getLogger(Client.class.getSimpleName());
@ -34,11 +34,11 @@ public class Client {
* Enters the online mode by acquiring a user ID from the server.
*
* @param credentials the login credentials of the user
* @throws IOException if the online mode could not be entered or the request
* failed for some other reason
* @throws Exception if the online mode could not be entered or the request
* failed for some other reason
* @since Envoy v0.2-alpha
*/
public void onlineInit(LoginCredentials credentials) throws IOException {
public void onlineInit(LoginCredentials credentials) throws Exception {
logger.info(String.format("Attempting connection to server %s:%d...", config.getServer(), config.getPort()));
socket = new Socket(config.getServer(), config.getPort());
logger.info("Successfully connected to server.");
@ -47,14 +47,20 @@ public class Client {
logger.finest("Sending login credentials...");
SerializationUtils.writeBytesWithLength(credentials, socket.getOutputStream());
// Read response (user object)
InputStream in = socket.getInputStream();
// Create message receiver
Receiver receiver = new Receiver(socket.getInputStream());
// Read object
try {
sender = SerializationUtils.read(in, User.class);
} catch (ClassNotFoundException e) {
throw new IOException(e);
// Register user creation processor
receiver.registerProcessor(User.class, sender -> { logger.info("Acquired user object " + sender); this.sender = sender; });
// Start receiver
new Thread(receiver).start();
// Wait for a maximum of five seconds to acquire the sender object
long start = System.currentTimeMillis();
while (sender == null) {
if (System.currentTimeMillis() - start > 5000) throw new EnvoyException("Did not log in after 5 seconds");
Thread.sleep(500);
}
online = true;

View File

@ -0,0 +1,15 @@
package envoy.client;
/**
* Project: <strong>envoy-client</strong><br>
* File: <strong>ObjectProcessor.java</strong><br>
* Created: <strong>30.12.2019</strong><br>
*
* @author Kai S. K. Engelbart
* @since Envoy v0.3-alpha
*/
public interface ObjectProcessor<T> {
void process(T input);
}

View File

@ -0,0 +1,50 @@
package envoy.client;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import envoy.client.util.EnvoyLog;
/**
* Project: <strong>envoy-client</strong><br>
* File: <strong>Receiver.java</strong><br>
* Created: <strong>30.12.2019</strong><br>
*
* @author Kai S. K. Engelbart
* @since Envoy v0.3-alpha
*/
public class Receiver implements Runnable {
private InputStream in;
private Map<Class<?>, ObjectProcessor<?>> processors = new HashMap<>();
private static final Logger logger = EnvoyLog.getLogger(Receiver.class.getSimpleName());
public Receiver(InputStream in) { this.in = in; }
@SuppressWarnings("unchecked")
@Override
public void run() {
try (ObjectInputStream oin = new ObjectInputStream(in)) {
while (true) {
Object obj = oin.readObject();
logger.finest("Received object " + obj);
// Get appropriate processor
ObjectProcessor processor = processors.get(obj.getClass());
if (processor == null)
logger.severe(String.format("The received object has the class %s for which no processor is defined.", obj.getClass()));
else
processor.process(obj);
}
} catch(Exception e) {
logger.log(Level.SEVERE, "Error on receiver thread", e);
}
}
public <T> void registerProcessor(Class<T> processorClass, ObjectProcessor<T> processor) { processors.put(processorClass, processor); }
}

View File

@ -101,6 +101,7 @@ public class Startup {
client.onlineInit(new LoginCredentials(userName, pass.toCharArray()));
} catch (Exception e1) {
logger.warning("Could not connect to server. Trying offline mode...");
e1.printStackTrace();
try {
// Try entering offline mode
localDB.loadUsers();