362 lines
9.5 KiB
Java
362 lines
9.5 KiB
Java
package de.unidue.iem.tdr.nis.client;
|
|
|
|
import java.io.BufferedReader;
|
|
import java.io.IOException;
|
|
import java.io.InputStreamReader;
|
|
import java.io.PrintWriter;
|
|
import java.net.ConnectException;
|
|
import java.net.Socket;
|
|
import java.net.UnknownHostException;
|
|
import java.security.MessageDigest;
|
|
import java.security.NoSuchAlgorithmException;
|
|
import java.util.ArrayList;
|
|
import java.util.Formatter;
|
|
import java.util.StringTokenizer;
|
|
|
|
/**
|
|
* Diese Klasse ermglicht die Kommunikation mit dem Server. Verbindungsauf und
|
|
* -abbau sind Ihnen in der Klasse {@link Client} schon vorgegeben. Fr Sie sind
|
|
* die Methoden {@link #sendSolution(String solution)}, {@link #getTask(int taskId)},
|
|
* {@link #getTask(int taskId, String[] params)} und
|
|
* {@link #sendMoreParams(TaskObject task, String[] params)} relevant.
|
|
* <p>
|
|
* Bitte verndern Sie diese Klasse nicht.
|
|
*
|
|
* @see Client
|
|
*
|
|
*/
|
|
public class Connection {
|
|
/* packettypes */
|
|
private final static int AUTHENTICATION = 1;
|
|
private final static int TASKREQUEST = 2;
|
|
private final static int SOLUTION = 3;
|
|
private final static int MOREPARAMS = 4;
|
|
private final static int BYE = Integer.MAX_VALUE;
|
|
|
|
/* Verbindungsinformationen */
|
|
private String host = "tmt.tdr.iem.uni-due.de";
|
|
private int port = 40001;
|
|
private Socket s = null;
|
|
private BufferedReader in = null;
|
|
private PrintWriter out = null;
|
|
private boolean ready = false;
|
|
private boolean serverClosed = false;
|
|
|
|
/** Zuletzt empfangenes Paket */
|
|
private String[] input;
|
|
|
|
/**
|
|
* Klassenkonstruktor. Baut die Verbindung zum Server auf.
|
|
*/
|
|
protected Connection() {
|
|
try {
|
|
s = new Socket(host, port);
|
|
s.setSoTimeout(3000);
|
|
in = new BufferedReader(new InputStreamReader(s.getInputStream()));
|
|
out = new PrintWriter(s.getOutputStream(), false);
|
|
|
|
getResponse();
|
|
for (int i = 1; i < input.length; i++)
|
|
System.out.println(input[i]);
|
|
ready = true;
|
|
} catch (UnknownHostException e) {
|
|
printErr(e,
|
|
"Der angegebene Hostname kann nicht aufgeloest werden.",
|
|
true);
|
|
} catch (ConnectException e) {
|
|
printErr(e, "Fehler beim Verbindungsaufbau.", true);
|
|
} catch (IOException e) {
|
|
printErr(e, "Der Server konnte nicht erreicht werden.", true);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gibt an, ob die Verbindungs zum Server bereit ist.
|
|
*
|
|
* @return true, falls die Verbindung besteht, sonst false
|
|
*/
|
|
protected boolean isReady() {
|
|
return ready;
|
|
}
|
|
|
|
/**
|
|
* Meldet einen Benutzer am Server an.
|
|
*
|
|
* @param userId
|
|
* Matrikelnr des Benutzers
|
|
* @param password
|
|
* Passwort des Benutzers
|
|
* @return true, wenn die Anmeldung erfolgreich war, ansonsten false.
|
|
*/
|
|
protected boolean auth(int userId, String password) {
|
|
String[] params = new String[2];
|
|
params[0] = String.valueOf(userId);
|
|
params[1] = hashPw(password);
|
|
sendRequest(AUTHENTICATION, params);
|
|
getResponse();
|
|
if (input.length == 2)
|
|
if (input[1].equalsIgnoreCase("STATUS_OK"))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Beendet die Verbindung mit dem Server.
|
|
*/
|
|
protected void close() {
|
|
try {
|
|
if (!serverClosed) {
|
|
out.println(BYE);
|
|
out.flush();
|
|
}
|
|
in.close();
|
|
out.close();
|
|
s.close();
|
|
System.out.println("Verbindung beendet.");
|
|
} catch (IOException e) {
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Ruft gezielt eine Aufgabe vom Server ab.
|
|
*
|
|
* @param taskId
|
|
* Identifikator der gewnschten Aufgabe
|
|
* @return Aufgabe in Form von TaskObject
|
|
*/
|
|
protected TaskObject getTask(int taskId) {
|
|
sendRequest(TASKREQUEST, String.valueOf(taskId));
|
|
getResponse();
|
|
TaskObject task = new TaskObject();
|
|
task.setType(taskId);
|
|
parseTaskObject(task);
|
|
return task;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* Ruft gezielt eine Aufgabe vom Server ab und sendet dabei Parameter mit.
|
|
*
|
|
* @param taskId
|
|
* Identifikator der gewnschten Aufgabe
|
|
* @param params
|
|
* Parameterliste
|
|
* @return Aufgabe in Form von TaskObject
|
|
*/
|
|
protected TaskObject getTask(int taskId, String[] params) {
|
|
String[] request = new String[params.length + 1];
|
|
request[0] = String.valueOf(taskId);
|
|
for (int i = 0; i < params.length; i++) {
|
|
request[i + 1] = params[i];
|
|
}
|
|
sendRequest(TASKREQUEST, request);
|
|
getResponse();
|
|
TaskObject task = new TaskObject();
|
|
task.setType(taskId);
|
|
parseTaskObject(task);
|
|
return task;
|
|
}
|
|
|
|
/**
|
|
* Sendet weitere Parameter an den Server
|
|
*
|
|
* @param task
|
|
* TaskObject in welches die Antwort vom Server geparst wird
|
|
* @param params
|
|
* Parameter-Liste
|
|
*/
|
|
protected void sendMoreParams(TaskObject task, String[] params) {
|
|
sendRequest(MOREPARAMS, params);
|
|
getResponse();
|
|
parseTaskObject(task);
|
|
}
|
|
|
|
/**
|
|
* Sendet eine Lsung an den Server
|
|
*
|
|
* @param solution
|
|
* Lsung des Studierenden
|
|
*/
|
|
protected boolean sendSolution(String solution) {
|
|
String[] params = new String[1];
|
|
params[0] = solution;
|
|
sendRequest(SOLUTION, params);
|
|
getResponse();
|
|
if (input[1].equalsIgnoreCase("SOLUTION_OK"))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Empfngt eine Antwort vom Server. Der Inhalt wird in this.input
|
|
* gespeichert, wenn der Server keinen Fehler meldet. Ansonsten wird die
|
|
* Fehlermeldung ausgegeben und die Verbindung vom Server beendet.
|
|
*/
|
|
private void getResponse() {
|
|
boolean error = false;
|
|
int status;
|
|
input = null;
|
|
try {
|
|
ArrayList<String> inputList = new ArrayList<String>();
|
|
String tmp = in.readLine();
|
|
|
|
if (tmp.equals(String.valueOf(Integer.MAX_VALUE))) {
|
|
serverClosed = true;
|
|
close();
|
|
System.exit(0);
|
|
}
|
|
|
|
status = Integer.parseInt(tmp.substring(0, 3));
|
|
|
|
if (status != 200) {
|
|
error = true;
|
|
System.out.println("Fehler: " + tmp);
|
|
}
|
|
|
|
while (tmp != null && !tmp.isEmpty()) {
|
|
inputList.add(tmp);
|
|
tmp = in.readLine();
|
|
if (error) {
|
|
System.out.println(tmp);
|
|
}
|
|
}
|
|
|
|
input = new String[inputList.size()];
|
|
inputList.toArray(input);
|
|
|
|
/*
|
|
* Server beendet bei einem Fehler immer die Verbindung. ->
|
|
* BYE-Paket empfangen.
|
|
*/
|
|
if (error)
|
|
getResponse();
|
|
|
|
} catch (IOException e) {
|
|
printErr(e, "E/A-Fehler beim Empfang einer Servernachricht.", true);
|
|
} catch (NumberFormatException e) {
|
|
printErr(e, "Fehlerhaftes Paket empfangen.", true);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Erzeugt einen SHA-1-Hash
|
|
*
|
|
* @param password
|
|
* zu hashendes Passwort
|
|
* @return SHA-1-Hash
|
|
*/
|
|
private String hashPw(String password) {
|
|
MessageDigest md;
|
|
Formatter fmt = new Formatter();
|
|
try {
|
|
md = MessageDigest.getInstance("SHA-1");
|
|
byte[] encryptPw = md.digest(password.getBytes());
|
|
for (int i = 0; i < encryptPw.length; i++) {
|
|
fmt.format("%02x", encryptPw[i] & 0xff);
|
|
}
|
|
} catch (NoSuchAlgorithmException e) {
|
|
// TODO Auto-generated catch block
|
|
e.printStackTrace();
|
|
}
|
|
|
|
return fmt.toString();
|
|
}
|
|
|
|
/**
|
|
* Gibt eine Fehlermeldung aus und beendet nach Bedarf das Programm.
|
|
*
|
|
* @param e
|
|
* Exception
|
|
* @param msg
|
|
* Fehlermeldung
|
|
* @param close
|
|
* true, wenn das Programm beendet werden soll, ansonsten false
|
|
*/
|
|
private void printErr(Exception e, String msg, boolean close) {
|
|
if (e != null)
|
|
e.printStackTrace();
|
|
System.err.println("Fehler: " + msg);
|
|
if (close) {
|
|
if (ready)
|
|
close();
|
|
System.exit(-1);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sendet eine Anfrage mit einem Parameter
|
|
*
|
|
* @param packetType
|
|
* Pakettyp-Identifikator
|
|
* @param param
|
|
* Parameter
|
|
*/
|
|
private void sendRequest(int packetType, String param) {
|
|
String[] params = new String[1];
|
|
params[0] = param;
|
|
sendRequest(packetType, params);
|
|
}
|
|
|
|
/**
|
|
* Sendet eine Anfrage (bestehend aus mindestens einem
|
|
* Pakettyp-Identifikator (Int) und optionalen Parametern) an den Server.
|
|
*
|
|
* @param packetType
|
|
* Identifikator des Pakettyps
|
|
* @param params
|
|
* Liste der Parameter als String-Array
|
|
*/
|
|
private void sendRequest(int packetType, String[] params) {
|
|
out.println(packetType);
|
|
if (params != null) {
|
|
for (int i = 0; i < params.length; i++)
|
|
out.println(params[i]);
|
|
}
|
|
out.println();
|
|
out.flush();
|
|
}
|
|
|
|
/**
|
|
* Erzeugt aus den eingehenden Daten die Inhaltsarrays eines TasksObjects
|
|
* Die Funktion geht davon aus, dass sie nur aufgerufen wird, wenn wirklich
|
|
* ein TaskObject bertragen wurde
|
|
*
|
|
* @param task
|
|
* TaskObject, das mit Daten gefllt werden soll
|
|
*/
|
|
private void parseTaskObject(TaskObject task) {
|
|
for (int i = 1; i < input.length;) {
|
|
StringTokenizer st = new StringTokenizer(input[i], "=");
|
|
if (st.countTokens() != 2) {
|
|
printErr(null, "Fehlerhaftes Paket erhalten.", true);
|
|
}
|
|
|
|
String tmp = st.nextToken();
|
|
if (tmp.equalsIgnoreCase("STRINGARRAY")) {
|
|
i++;
|
|
int length = Integer.parseInt(st.nextToken());
|
|
task.setStringArray(new String[length]);
|
|
for (int j = 0; j < length; j++) {
|
|
task.setStringArray(input[i + j], j);
|
|
}
|
|
i += length;
|
|
} else if (tmp.equalsIgnoreCase("INTARRAY")) {
|
|
i++;
|
|
int length = Integer.parseInt(st.nextToken());
|
|
task.setIntArray(new int[length]);
|
|
for (int j = 0; j < length; j++) {
|
|
task.setIntArray(Integer.parseInt(input[i + j]), j);
|
|
}
|
|
i += length;
|
|
} else if (tmp.equalsIgnoreCase("DOUBLEARRAY")) {
|
|
i++;
|
|
int length = Integer.parseInt(st.nextToken());
|
|
task.setDoubleArray(new double[length]);
|
|
for (int j = 0; j < length; j++) {
|
|
task.setDoubleArray(Double.parseDouble(input[i + j]), j);
|
|
}
|
|
i += length;
|
|
}
|
|
}
|
|
}
|
|
} |