Musterlösung Aufgabe 1.1/1.2: server #!/usr/bin/perl use Socket; use Sys::Hostname; use Time::HiRes qw(gettimeofday); my $port = shift @ARGV || 12345; my $iaddr = gethostbyname(hostname()); my $proto = getprotobyname(’udp’); my $paddr = sockaddr_in($port, $iaddr); socket(SOCKET, PF_INET, SOCK_DGRAM, $proto) || die "socket: $!"; bind(SOCKET, $paddr) || die "bind: $!";; while(1) { my ($msg, $hisaddr, $hisport, $hisiaddr); ($hisaddr = recv(SOCKET, $msg, 8, 0)) || die("recv: $!"); my $repl = $msg . pack("L2", gettimeofday); send(SOCKET, $repl, 0, $hisaddr) } Hans P. Reiser (Abteilung Verteilte Systeme) AVS Aufgabe 1 4. November 2005 1/7 Musterlösung Aufgabe 1.1/1.2: client (1/2) #!/usr/bin/perl use Socket; use Sys::Hostname; use Time::HiRes qw(gettimeofday); # Parse command line arguments my $host = shift @ARGV || ’localhost’; my $port = shift @ARGV || 12345; my $hishost = gethostbyname($host) or die "gethostbyname $host: $!"; # Create local socket my $proto = getprotobyname(’udp’); my $iaddr = gethostbyname(hostname()); my $paddr = sockaddr_in(0, $iaddr); socket(SOCKET, PF_INET, SOCK_DGRAM, $proto) || die "socket: $!"; bind(SOCKET, $paddr) || die "bind: $!"; Hans P. Reiser (Abteilung Verteilte Systeme) AVS Aufgabe 1 4. November 2005 2/7 Musterlösung Aufgabe 1.1/1.2: client (2/2) # Send probe message my $hisaddr = sockaddr_in($port, $hishost); my $msg = pack("L2", gettimeofday); send(SOCKET, $msg, 0, $hisaddr); # Wait for reply, process reply my $repl; ($hisaddr = recv(SOCKET, $repl, 16, 0)) || die("recv: $!"); my $t3 = time(); my $t1 = timedecode(substr($repl,0,8)); my $t2 = timedecode(substr($repl,8,8)); printf("Offset: %.3f +/- %.3f\n", ($t3+$t1)/2-$t2, ($t3-$t1)/2); sub timedecode { my $str = shift; my ($sec, $usec) = unpack("L2",$str); return $sec + 0.000001 * $usec; } Hans P. Reiser (Abteilung Verteilte Systeme) AVS Aufgabe 1 4. November 2005 3/7 Lösung in Java: server import java.io.*; import java.net.*; public class server { public static void main(String[] args) { long currentTime; int port = Integer.parseInt(args[0]); try { ServerSocket connectionSocket = new ServerSocket( port ); } catch ( IOException ioex ) { System.out.println("Cannot create server socket: "+ioex); System.exit(-1); } while(true){ // Warten auf Clienten try { Socket client = connectionSocket.accept(); PrintWriter out = new PrintWriter(client.getOutputStream(), true); BufferedReader in = new BufferedReader( new InputStreamReader( client.getInputStream() ) ); String command = in.readLine(); if ( command.compareTo("Time")==0 ) { out.println(System.currentTimeMillis()); } } catch ( IOException ioex ) { System.out.println("Failed: "+ioex.getClass()+": "+ioex.toString()); System.exit(-1); } } } } Hans P. Reiser (Abteilung Verteilte Systeme) AVS Aufgabe 1 4. November 2005 4/7 Lösung in Java: client (1/2) import java.io.*; import java.net.*; public class client { public static void main(String[] args) { PrintWriter out = null; BufferedReader in = null; try { // Sockets erzeugen, Streams anlegen Socket s = new Socket( args[0], Integer.parseInt(args[1]) ); out = new PrintWriter(s.getOutputStream(), true); in = new BufferedReader(new InputStreamReader( s.getInputStream())); } catch (Exception e) { System.err.println("Cannot create socket: "+e); System.exit(1); } // Erst lokale Zeit abfragen, dann Anfrage an Server long t1 = System.currentTimeMillis(); out.println("Time"); Hans P. Reiser (Abteilung Verteilte Systeme) AVS Aufgabe 1 4. November 2005 5/7 Lösung in Java: Client (2/2) try { // Auf Antwort von Server warten und diese verarbeiten. String receivedData = in.readLine(); long t3 = System.currentTimeMillis(); long t2 = Long.parseLong(receivedData); // Maximalen Fehler ausrechnen long maxDist = t3 - t1; double offset = ( (t1-t2)+(t3-t2) )/2; // Ergebnis ausgeben System.out.println("Offset: " + offset*0.001 + "s +/-" + maxDist*0.001 + "s"); } catch( IOException ioex ){//Fehlerbehandlung System.exit(-1); } System.exit(0); } } Hans P. Reiser (Abteilung Verteilte Systeme) AVS Aufgabe 1 4. November 2005 6/7 Uhrenmanipulation libtimemagic auf Homepage export export export export export LD_PRELOAD=/<...>/libtimemagic.so.0.0 TIMEMAGIC_VERBOSE=1 [optional] TIMEMAGIC_OFFSET=100 [in Sekunden] TIMEMAGIC_DRIFT=1000 [in ppm] TIMEMAGIC_REF=‘perl -e "print time"‘ [Epoch-Sekunden date bin/client ... ... Hans P. Reiser (Abteilung Verteilte Systeme) AVS Aufgabe 1 4. November 2005 7/7