Ein verteiltes System ist im Prinzip der Zusammenschluss mehrerer Rechner zur Lösung einer gemeinsamen Aufgabe. Eines der größten verteilten Systeme ist das Internet mit seinen Applikationen. Teil 2 beschreibt die Kommunikation über das Netzwerk mittels TCP, UDP und Sockets. Im Anschluss folgt die Verwendung von Remote Procedure Calls.
| Skript-Annfang | VS_1_So2014 – Seite 1 |
|---|---|
| Skript-Ende | VS_6_So2014 – Seite 70 |
Netzwerkkommunikation
Kommunikationsformen
Welche Kommunikationsformen gibt es?
- Verbindungslos (UDP)
- Verbindungsorientiert (TCP)
- Synchron (Blockiert und wartet auf Antwort)
- Asynchron (Kein Blockieren)
Wo sind die Unterschiede zwischen verbindungsloser und verbindungsorientierter Kommunikation?
| Verbindungslos | Verbindungsorientiert | |
| Protokoll | UDP | TCP |
| Reales Beispiel | Brief | Telefongespräch |
| Verbindung | Wird nicht ausgehandelt | Wird ausgehandelt mittels Handshake (Auf- und Abbau) |
| Paketverlust | Kann passieren | Zustellung wird garantiert |
| Reihenfolge | Nicht gewährleistet und muss von Anwendung geprüft werden | Reihenfolge wird garantiert |
| Broadcast/Multicast | Ja | Nein |
Was ist die synchrone Kommunikation?
- Sender wird blockiert bis Antwort eintrifft

Was ist die asynchrone Kommunikation?
- Sender wird nicht blockiert
- Ergebnis muss explizit gesendet werden

Welche Kommunikationsform ist am besten geeignet in einem verteilten System?
- Das kommt auf die Art des verteilten Systems an
Was kann bei synchroner Kommunikation passieren?
- Wenn eine Nachricht verloren geht, wird der Absender blockiert
- Wenn der Empfänger ausfällt, wird der Absender blockiert
Qualitätsparameter
Welche Qualitätsparameter gibt es?
| Merkmal | Beschreibung |
| Latenz | Dauer des Transfers einer leeren Nachricht zwischen Sender und Empfänger |
| Datentransferrate | Datenmenge, die innerhalb einer Zeiteinheit über einen Übertragungskanal übertragen wird |
| Nachrichtentransferzeit | Dauer des Transfers einer Nachricht (Latenz + Datenmenge / Datentransferrate) |
| Durchsatz | Datenmenge pro Zeiteinheit |
| Bandbreite | Maximale Übertragungsrate |
Warum ist Latenz nicht gleich Nachrichtentransferzeit?
- Die Latenzzeit ist die Zeit, die eine Nachricht ohne Nutzdaten durch die Kommunikationsschichten und das Netzwerk braucht
- Die Nachrichtentransferzeit errechnet sich aus Latenz + Datenmenge / Datentransferrate
Bei welchen Anwendungen ist Latenz, wo ist Bandbreite wichtiger?
- Latenz wird benötigt, wenn Informationen schnell von System A zu System B transportieren müssen
- Bandbreite wird benötigt, wenn große Datenmengen von System A zu System B transportieren müssen
Warum kann die Bandbreite i.d.R. von einer Anwendung nicht voll ausgeschöpft werden?
- Pakete werden immer mit einem Header versehen, der selbst einen Teil der Bandbreite beansprucht
- Die Bandbreite wird in der Regel von mehreren Anwendungen gleichzeitig beansprucht
Warum ist das wichtig für verteilte Systeme?
- Der Durchsatz von Daten im Netz ist limitiert
- Daten müssen bei Synchronisation schnell übertragen werden
Netzwerkgrundlagen
Wie ist ein Paket aufgebaut?
- Protokolldaten (Header) besteht aus Adressen, Ports und TTL
- Nutzdaten
Was ist das OSI-Schichtenmodell?
- 7 Schichten mit funktionalen Teilaufgaben
- Jede Schicht hat eigene Protokolle
- Jedes Protokoll fügt seinen eigenen Header an die Pakete an
- Nachrichten durchlaufen diese 7 Schichten
- Verteilte Systeme arbeiten auf Schicht 4 bis 7
Wie funktioniert das Internet?
- Es besteht aus vielen heterogenen unabhängigen Netzwerken
- Diese Netzwerke werden mit Routern verbunden
- Die Router stehen miteinander in Verbindung
- Pakete werden aus dem Netzwerk an den Router geleitet
- Beim Ziel leitet ein Router die Pakete wieder in ein Netzwerk
Was ist Routing?
- Mehrere mögliche Wege zwischen Sender und Empfänger
- Routing wählt anhand einer Metrik den besten Weg
- Beeinflusst dadurch die Übertragungsdauer von Nachrichten
Protokolle
Was ist das IP-Protokoll?
- Logische IP-Adressierung
- Arbeitet auf Layer 3
- Verbindungslos (Paketverluste möglich)
- Duplikate möglich
- Keine Reihenfolge
Was ist das UDP-Protokoll?
- Zusätzliches Attribut „Port“ für Adressierung von Diensten
- Verbindungslos (Paketverluste möglich)
- Duplikate möglich
- Keine Reihenfolge
- Arbeitet auf Layer 4
- Multicast-fähig
- Kleinerer Header (schneller)
- Maximal 64 KB große Pakete
Was ist das TCP-Protokoll?
- Zusätzliches Attribut „Port“ für Adressierung von Diensten
- Verbindungsorientiert (Keine Paketverluste)
- Keine Duplikate (Verwerfen)
- Reihenfolge wird eingehalten
- Arbeitet auf Layer 4
- Kein Multicast
- Größerer Header (langsamer)
Welches Protokoll ist für welche verteilte Anwendung am besten geeignet?
| Anwendung | Protokoll |
|---|---|
| Videokonferenz | UDP |
| DNS | UDP/TCP |
| Bank-Transaktionen | TCP |
| Webserver | TCP |
Für welche Qualitätsparameter ist der Paketaufbau wichtig?
- Für alle Parameter, die von der Datenmenge abhängen wie die Nachrichtentransferzeit
Welche Probleme kann es dennoch geben?
- Pakete können trotz aller Maßnahmen verloren gehen
- Pufferüberlauf oder Nichtabholen von UDP-Paketen
- Deadlocks
Was macht man im Fehlerfall?
- Nicht blockieren
- Timeouts
setsockoptoderselect
Sockets
Was sind Sockets?
- Bi-direktionaler Kommunikationsendpunkt
- Wird von UDP und TCP genutzt
- Wird als Objekt im Speicher dargestellt
- Besteht aus IP-Adresse und Port
- Ports von Client und Server können unterschiedlich sein
Was braucht man zum Datenaustausch, um ein funktionierendes verteiltes System aufzubauen?
- Gemeinsames Datenformat
Sockets mit UDP
- Entwickler müssen sich selbst um Reihenfolge, Segmentierung und Fehlerkorrektur kümmern
send(2x 5 Byte) werden alsrecv(2x 5 Byte) empfangen- Verlorene Datenpakete müssen beachtet werden
- Ein Socket kann an viele Adressen Pakete schicken
Wie läuft die Kommunikation mit UDP-Sockets ab?
- Nachricht kleiner als 64 KB wird versendet mittels
sendto() - Socket empfängt mittels
recvfrom()– alles (ok), nichts (Verlust) oder nur einen Teil (Puffer zu klein)

Was passiert, wenn man den Server an keine Adresse bindet?
- Server bzw. Dienste werden auf festen Adressen angesprochen
- Clients wissen sonst nicht, wohin sie sich verbinden sollen
- Das System weist dann seinem Dienst selbst einen Port zu
- Bei Clients ist das egal, der Server antwortet bei Anfragen auf den Quellport des Clients
Woher weiß das UDP-Socket wie groß die Nachricht ist?
- Zeichen für Anfang und Ende
- Protokoll mit Header-Informationen
Wie verschickt man Nachrichten größer als 64 KB?
- Aufteilen der Nachricht in kleinere Blöcke
- While-Schleife mit
recvfrom()bis alle Daten empfangen sind
Sockets mit TCP
- Verbindung muss im Programm aufgebaut werden
- Pakete werden als Datenstrom versendet (Automatische Segmentierung)
send(2x 5 Byte) werden alsrecv(1x 10 Byte) empfangen
Was passiert wenn der Server eine Anfrage akzeptiert?
- Erzeugt einen neuen Socket über den nun kommuniziert wird
- Der eigentliche Socket wartet weiter auf neue Anfragen
Wie läuft die Kommunikation mit TCP-Sockets ab?
- Nachricht wird definiert und versendet mittels
send() - Socket auf Empfängerseite empfängt mittels
recv()– alles (ok), nichts (Verlust) oder beliebig viele Teilnachrichten

Was passiert in der Anwendung wenn Pakete verloren gehen oder vertauscht werden?
- Datenstrom verzögert oder angehalten
- Verbindung bricht ab (recv = -1)
Woher weiß das TCP-Socket wie lang die Nachricht ist?
- Wenn
recv()0 zurück liefert, ist die TCP-Verbindung erfolgreich abgebaut und alle Pakete empfangen - Wenn
recv()X > 0 zurück liefert, wurden X Byte empfangen
Sind Sockets synchron?
- Standardmäßig sind alle Aufrufe synchron bzw. blockierend
Wie kann man asynchrones Verhalten erreichen?
- Threads mit eigenen Sockets
- Socket nicht-blockierend schalten mittels setsockopt und regelmäßig Daten pollen
- Select-Funktion überwacht die Sockets
Warum ist der Einsatz von select asynchron?
- Es wird nur ein Thread blockiert und nicht viele Threads
Was bringen Sockets im Hinblick auf die Transparenzeigenschaften?
- Nichts
was bringen Sockets im Hinblick auf die anderen Ziele eines verteilten Systems?
- Offenheit
Datenformate
Was passiert, wenn man einen Integer über ein Socket zu einem anderen Rechner schickt und dort ausgibt?
- Die Bitfolge der Zahl ist invertiert
- Die Zahl befindet sich in network byte order (big endian)
- Sie muss über einen Befehl korrigiert werden
Welche Zahlenumwandlungen gibt es?
ntohs– network-to-host shortntohl– network-to-host longhtons– host-to-network shorthtonl– host-to-network long
Remote Procedure Calls (RPC)
Was sind RPCs?
- Technik zur Realisierung von Interprozesskommunikation
- 1 Funktionsaufruf statt vieler Socketfunktionen
- Schnittstellen verbergen Komplexität
- Lokaler Funktionsaufruf zu einem Stub für Parameter und Rückgabewert
Welche Ziele guter verteilter Systeme werden erfüllt?
- Verteilungstransparenz
- Einfacher Zugriff auf Ressourcen
Wie funktioniert ein Stub?
- Client ruft Funktion auf, die auf einen Stub zugreift
- Client-Stubs erstellen aus den Parametern Nachrichten (Serialisierung/marshalling)
- Stubs transportieren diese Nachrichten mittels Transportprotokoll über das Netzwerk (send/recv)
- Server-Stubs werden entpackt (Deserialisierung/demarshalling)
- Parameter werden rekonstruiert und die Server-Funktion aufgerufen

Müssen wie bei Sockets die Zahlen konvertiert werden?
- Nein, das passiert innerhalb der Stubs
- RPCs liefern dafür eigene Datentypen mit
Was sind die Vorteile von RPCs?
- Bequemere, einfachere Beschreibung der Datenübertragung
- Synchrone und asynchrone Aufrufe
- Transportprotokolle können frei ausgewählt werden
Was sind die Nachteile von RPCs?
- Kein gemeinsamer Adressraum (keine Pointer oder Referenzen)
- RPCs sind standardmäßig unverschlüsselt
- RPCs sind weniger performant
- Keine Fehlerbehandlung
- Sockets sind flexibler (Keine Einschränkungen)
- Viele Dinge müssen immer noch selbst erledigt werden (IDL compilieren, Daemons starten und Adressierungen)
Was ist eine Interface Definition Language (IDL)?
- Jede RPC-Technik hat eine eigene Beschreibungssprache (Interface Definition Language)
- Definiert die unterstützen Datentypen
- Beschreibt die RPC Funktionen (nur Signatur, keine Implementierung)
- Compiler erzeugt Stubs bzw. Quellcode für Client und Server
- Der Vorlagen-Code muss dann ergänzt werden
Woher kommen die Stubs?
- Compiler erzeugt die Stubs aus der IDL
Wie implementiert man Aufruf und Funktion?
- Werden selbst implementiert
Welche Programmiersprachen werden unterstützt?
| Framework | Sprachen |
|---|---|
| Apache Thrift | C, C++, Java u.v.m. |
| Sun ONC-RPC | C |
| XML-RPC | RPC Aufrufe als XML codiert |
| JSON-RPC | Wie XML-RPC, nur mit JSON |
Wie implementiert man einen Service?
- Schnittstelle in IDL formulieren
- IDL compilieren
- Funktionen auf Server implementieren
- Funktionsaufrufe im Client implementieren
Apache Thrift
Welche Protokolle verwendet Thrift?
- Netzwerkprotokolle austauschbar
- Standardmäßig wird TCP verwendet
Wie adressiert man den Server?
- IP-Adresse und Port im Client
Welche Datentypen kennt Thrift?
- bool
- binary
- byte
- i16, i32 und i64
- string
- struct
- list
- set
- map
Wie implementiert man die IDL bzw. Schnittstelle?
service Calculator {
void ping(),
}
i32 add(1: i32 num1, 2: i32 num2)
Wie kompiliert man die IDL?
$> thrift gen cpp calc.thrift
Wie implementiert man den Server?
class calculatorHandler : virtual public calculatorIf
{
public:
calculatorHandler()
{
// Your initialization goes here
}
void ping()
{
// Your implementation goes here
printf("ping\n");
}
int32_t add(const int32_t num1, const int32_t num2)
{
// Your implementation goes here
printf("add\n");
}
};
int main(int argc, char **argv) {
int port = 9090;
shared_ptr<calculatorHandler> handler(new calculatorHandler());
shared_ptr<TProcessor> processor(new calculatorProcessor(handler));
shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);
server.serve();
return 0;
}
Wie implementiert man den Client?
#include "calculator.h"
int main()
{
try
{
// Variablen initialisieren
int n1 = 2, n2 = 3;
// Verbindung auf Port 9090 öffnen
shared_ptr<TSocket> socket(new TSocket("localhost", 9090));
shared_ptr<TTransport> transport(new TBufferedTransport(socket));
shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
CalculatorClient client(protocol);
transport->open();
// Aufruf der Serverfunktion mit Rückgabewert
int result = client.add(n1,n2);
// Verbindung schließen
transport->close();
// Ausgabe
cout << n1 << " + " << n2 << " = " << result << endl;
}
catch(TException &tx)
{
cout << "error calling server: " << tx.what() << endl;
}
return 0;
}
Wie implementiert man eigene Datentypen?
struct UserProfile {
1: i32 uid,
2: string name,
3: string blurb
}
service UserStorage {
void store(1: UserProfile user),
UserProfile retrieve(1: i32 uid)
}
ONC RPC
Was ist ONC RPC?
- Eine der ersten RPC Implementierungen
- Implementiert im Network File System (NFS)
- Entwickler schreibt IDL, Client und Server
- Im Server wird keine IP-Adresse und kein Port angegeben
- Server wird über einen Daemon adressiert
Welche Datenformate unterstützt ONC RPC?
- (unsigned) int
- (unsigned) float
- string
- bool
- struct
- union
Wie sieht eine Schnittstelle aus?
/* calc.x: Remote calculator */
struct numbers {
int n1;
int n2;
};
program CALCULATORPROG {
version CALCULATORVERS {
int add(numbers) = 1;
} = 1;
} = 0x20000001;
//version = 0x20000001
//program = 1

Wie findet der Client den Server ohne Port?
- Man benötigt einen Mechanismus, um RPC Server adressieren zu können
- RPC daemon (rpcbind/portmap) auf jedem der beteiligten Rechner (Client und Server)
- Beim Start des Servers registriert sich der Server bei einem lokalen Daemon
- Der Client muss die IDs für
versionundprogramangeben - Client benötigt nur die IP-Adresse des Servers
- Port des Daemons ist festgelegt auf 111
XML-RPC
Was ist XML-RPC?
- XML als Datenaustauschformat
- Große Anzahl an unterstützten Sprachen
- HTTP als Transportprotokoll
- Als Server kann ein Webserver dienen, der XML-RPC versteht
- Keine Schnittstellensprache
Wie sieht ein Aufruf aus?
POST /RPC2 HTTP/1.0 User-Agent: Frontier/5.1.2 (WinNT) Host: betty.userland.com Content-Type: text/xml Content-length: 181 <?xml version="1.0"?> <methodCall> <methodName>examples.getStateName</methodName> <params> <param> <value><i4>41</i4></value> </param </params> </methodCall> </?xml>
Wie sieht eine Antwort aus?
HTTP/1.1 200 OK Connection: close Content-Length: 158 Content-Type: text/xml Date: Fri, 17 Jul 1998 19:55:08 GMT Server: UserLand Frontier/5.1.2-WinNT <?xml version="1.0"?> <methodResponse> <params> <param> <value><string>South Dakota</string></value> </param> </params> </methodResponse> </?xml>
Wie sieht ein Client aus?
string const serverUrl("http://localhost:8080/RPC2");
string const methodName("sample.add");
xmlrpc_c::clientSimple myClient;
xmlrpc_c::value result;
// Aufruf
myClient.call(serverUrl, methodName, "ii", &result, 5, 7);
// Ergebnis
int const sum = xmlrpc_c::value_int(result);
cout << "Result of RPC (sum of 5 and 7): " << sum << endl;
Wie sieht ein Server aus?
class sampleAddMethod : public xmlrpc_c::method {
public:
sampleAddMethod() {
// signature and help strings are documentation -- the client
// can query this information with a system.methodSignature and
// system.methodHelp RPC.
this->_signature = "i:ii";
// method's result and two arguments are integers
this->_help = "This method adds two integers together";
}
void execute(xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retvalP) {
int const addend(paramList.getInt(0));
int const adder(paramList.getInt(1));
paramList.verifyEnd(2);
*retvalP = xmlrpc_c::value_int(addend + adder);
}
Protocol Buffers
Was sind Protocol Buffers?
- Austauschformat für Datenstrukturen
- Bieten Serialisierung und Deserialisierung an
- Übertragung läuft über Sockets
Was sind die Vorteile?
- Maximale Flexibilität bei der Implementierung der Übertragung
Was sind die Nachteile?
- Netzwerkkommunikation über Sockets muss selbst erledigt werden