|
|
@ -10,46 +10,84 @@ import java.text.SimpleDateFormat; |
|
|
|
import java.util.Date; |
|
|
|
|
|
|
|
class UDPTimeCounterClient { |
|
|
|
|
|
|
|
/** |
|
|
|
* Gibt einen Zeitstempel (timestamp) formatiert auf der Konsole aus. Der |
|
|
|
* Zeitstempel wird in aktuellen Millisekunden seit 1.1.1970 (UTC) und als |
|
|
|
* formatiertes Datum inkl. Uhrzeit ausgegeben. Der Ausgabe wird der übergebene |
|
|
|
* String outputPrefix vorangestellt. |
|
|
|
* |
|
|
|
* @param outputPrefix |
|
|
|
* String der als Beschreibung des Zeitpunkts vor die Ausgabe des |
|
|
|
* timestamp gestellt wird. |
|
|
|
* @param timestamp |
|
|
|
* Zeitstempel basierend auf System.currentTimeMillis() |
|
|
|
*/ |
|
|
|
private static void printFormattedTimestamp(String outputPrefix, long timestamp) { |
|
|
|
DateFormat df = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss"); |
|
|
|
System.out.println(outputPrefix + " = " + timestamp + " ms, " + df.format(new Date(timestamp))); |
|
|
|
} |
|
|
|
|
|
|
|
public static void main(String args[]) throws Exception { |
|
|
|
String hostname = ""; |
|
|
|
int udpPort = 36038; |
|
|
|
BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in)); |
|
|
|
DatagramSocket clientSocket = new DatagramSocket(); |
|
|
|
byte[] sendData = new byte[1024]; |
|
|
|
byte[] receiveData = new byte[1024]; |
|
|
|
DateFormat df = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss"); |
|
|
|
long timestampStart, timestampSent, timestampEnd, delay; |
|
|
|
|
|
|
|
// Socket erzeugen |
|
|
|
DatagramSocket clientSocket = new DatagramSocket(); |
|
|
|
|
|
|
|
// Hostname vom Benutzer anfragen auf dem der Server läuft |
|
|
|
System.out.println("Bitte geben Sie die Server-Adresse ein: "); |
|
|
|
hostname = inFromUser.readLine(); |
|
|
|
InetAddress IPAddress = InetAddress.getByName(hostname); |
|
|
|
|
|
|
|
// Zahl vom Benutzer abfragen, die dann vom Server auf den aktuellen Zählerstand |
|
|
|
// addiert wird |
|
|
|
System.out.println("Bitte geben Sie eine Zahl ein: "); |
|
|
|
Long number = new Long(inFromUser.readLine()); |
|
|
|
sendData = number.toString().getBytes(); |
|
|
|
|
|
|
|
// Zahl an Server senden |
|
|
|
System.out.println(System.lineSeparator()); |
|
|
|
long timestampStart = System.currentTimeMillis(); |
|
|
|
System.out.println("Zeit vor Versand = " + timestampStart + " ms, " + df.format(new Date(timestampStart))); |
|
|
|
timestampStart = System.currentTimeMillis(); |
|
|
|
printFormattedTimestamp("Zeit vor Versand", timestampStart); |
|
|
|
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, udpPort); |
|
|
|
clientSocket.send(sendPacket); |
|
|
|
long timestampSent = System.currentTimeMillis(); |
|
|
|
System.out.println("Zeit nach Versand = " + timestampSent + " ms, " + df.format(new Date(timestampSent))); |
|
|
|
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); |
|
|
|
timestampSent = System.currentTimeMillis(); |
|
|
|
printFormattedTimestamp("Zeit nach Versand", timestampSent); |
|
|
|
|
|
|
|
// Antwort mit neuem Zählerstand und Timestamp vom Server empfangen |
|
|
|
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); |
|
|
|
clientSocket.receive(receivePacket); |
|
|
|
timestampEnd = System.currentTimeMillis(); |
|
|
|
printFormattedTimestamp("Zeit nach Empfang", timestampEnd); |
|
|
|
|
|
|
|
long timestampEnd = System.currentTimeMillis(); |
|
|
|
System.out.println("Zeit nach Empfang = " + timestampEnd + " ms, " + df.format(new Date(timestampEnd))); |
|
|
|
long delay = timestampEnd - timestampStart; |
|
|
|
// Delay als Zeit zwischen timestampSent und timestampEnd berechnen und |
|
|
|
// ausgeben |
|
|
|
delay = timestampEnd - timestampStart; |
|
|
|
System.out.println("Delay = " + delay + " ms"); |
|
|
|
System.out.println(System.lineSeparator()); |
|
|
|
|
|
|
|
// Antwort vom Server auswerten und ausgeben |
|
|
|
String result = new String(receivePacket.getData()); |
|
|
|
System.out.println("Ausgabe vom Server:" + System.lineSeparator() + result); |
|
|
|
// Vom Server übergebenen Zeitstempel aus der Antwort herausschneiden |
|
|
|
// |
|
|
|
// Format Ausgabe vom Server "<Zählerstand> Zeit: <Zeitstempel> <Datum/Uhrzeit>" |
|
|
|
// Beispiel: 60 Zeit: 1510735274021 15.11.2017 08:41:14 |
|
|
|
long timestampServer = new Long(result.split(" ")[2]).longValue(); |
|
|
|
// One-Way-Delay (Bitverzögerung) aus Rount-Trip-Time (RTT) ermitteln |
|
|
|
float oneWayDelayEstimate = (timestampEnd - timestampSent) / 2; |
|
|
|
// Zeitabweichung zwischen Client und Server ermitteln (Zeitstempel vom Server |
|
|
|
// minus Zeitstempel bei Versand am Client minus One-Way-Delay) |
|
|
|
float timestampSkew = timestampServer - timestampSent - oneWayDelayEstimate; |
|
|
|
System.out.println("Zeitversatz zwischen Server und Client ca. = " + timestampSkew + " ms"); |
|
|
|
System.out.println(System.lineSeparator()); |
|
|
|
|
|
|
|
// Socket schließen |
|
|
|
clientSocket.close(); |
|
|
|
} |
|
|
|
} |