Verteilte Systeme Übung 4 Alexander Ploß Gruppe PVS (Parallele und Verteilte Systeme) Institut für Informatik Westfälische Wilhelms-Universität Münster Sommersemester 2008 Entwickler/User−Space TCP/IP Stack Web−Browser, E−Mail,. Anwendung Andere Anwendungen (erfordern spezielle Optimierung) Appl.−Protokolle: FTP, HTTP, SMTP, ... Andere Anwendungen Middleware: CORBA, RMI Programming Interface (Sockets) Betriebssystem TCP IGMP ICMP RARP ARP UDP Transport RIP IP OSPF Vermittlung Ethernet WLAN ... ATM Netzzugang 4-2 Aufgabe 1: Korrektur für 64bit Systeme Vorgabe: /∗ Service−Schleife ∗/ while (1) { int connsocket, retval; clientrequest req; size_t claddr_size; [..] /∗ blockierend auf eingehende Verbindung warten ∗/ connsocket = accept (listensocket, (struct sockaddr ∗) &claddr, &claddr_size); size_t ist hier laut man 2 accept nicht korrekt: int accept(int sockfd, struct sockaddr ∗addr, socklen_t ∗addrlen); Das Führt auf 64bit Systemen leider zu einem Fehler Korrektur: /∗ Service−Schleife ∗/ while (1) { int connsocket, retval; clientrequest req; socklen_t claddr_size; [..] 4-3 4.1 Aufgabe 1 Protokoll des Dateidienstes Client-Anfragen: Client-Anforderung Datei empfangen (GET) Zusatz Dateiname Server-Antworten: Server-Antwort Datei übermitteln (OK) Datei nicht gefunden (NOT FOUND) Ungültige Anfrage (BAD REQUEST) Zusatz Dateilänge und Dateiinhalt - Mögliche Erweiterungen: Client-Anforderung Verzeichnisinhalt anzeigen (LIST) Datei löschen (DEL) Datei übermitteln (PUT) Zusatz Dateiname Dateiname, Dateigröße, Dateiinhalt 4-4 4.1 Aufgabe 1 Datenstrukturen des Protokolls (fileprotocol.h) Mögliche Client-Anfragen enum file_clientcommand { FP_GET }; Mögliche Server-Antworten enum file_serverretcode { FP_OK = 0, FP_BADREQUEST, FP_FILENOTFOUND, FP_GENERROR }; 4-5 4.1 Aufgabe 1 Datentyp Client-Anfrage typedef struct { int reqlen; int cmd; /∗ file_clientcommand ∗/ char filename[FP_MAXFILENAME]; } clientrequest; Datentyp Server-Antwort (statischer Teil) typedef struct { int retcode; /∗ file_serverretcode ∗/ int filelen; } serverresponse; 4-6 4.1 Aufgabe 1 Generische sendMsg-Funktion /∗ Sendet &len Bytes beginnend bei msg ueber sock, Gibt −1 bei Fehler und 0 bei Erfolg zurueck, Tatsächliche Anzahl gesendeter Bytes wird in len geschrieben ∗/ int sendMsg(int sock, char ∗msg, int ∗len) { int total = 0; int bytesleft = ∗len; int n; while(total < ∗len) { n = send(sock, msg + total, bytesleft, 0); if (n == −1) { break; } total += n; bytesleft −= n; } ∗len = total; return n==−1?−1:0; } 4-7 4.1 Aufgabe 1 Versenden der Client-Anfrage (fileclient.c) /∗ Request an Server ueber sock senden ∗/ int send_request(int ∗sock, char ∗filename) { clientrequest req; [...] /∗ Request ausfuellen ∗/ req.cmd = FP_GET; req.cmd = htonl(req.cmd); strncpy(req.filename, filename, FP_MAXFILENAME); /∗ Nachricht senden ∗/ sendMsgSize = sizeof(req); retval = sendMsg(∗sock, (char∗)&req, &sendMsgSize); /∗Fehlerbehandlung entsprechend retval∗/ } Das direkte Versenden des struct clientrequest ist problematisch, Größe und Alignment kann auf verschiedenen Architekturen unterschiedlich sein! ⇒ Eigenes Marshalling/Unmarshalling: clreq_to_char und char_to_clreq-Funktionen implementieren 4-8 4.1 Aufgabe 1 Empfang der Server-Antwort (fileclient.c) /∗ Reply vom Server ueber sock empfangen ∗/ int recv_reply(int ∗sock) { char buffer[BUFSIZE]; serverresponse resp; /∗ Antwort empfangen ∗/ bytesrcvd = recv(∗sock, &resp, sizeof(resp), 0); /∗[..] Fehlerbehandlung entsprechend bytesrcvd∗/ resp.retcode = ntohl(resp.retcode); resp.filelen = ntohl(resp.filelen); if(resp.retcode == FP_BADREQUEST) err("Server responded: FP_BADREQUEST\n"); if(resp.retcode == FP_FILENOTFOUND) err("Server responded: FP_FILENOTFOUND\n"); if(resp.retcode == FP_GENERROR) err("Server responded: FP_GENERROR\n"); 4-9 4.1 Aufgabe 1 /∗ Datei empfangen und ausgeben ∗/ if(resp.retcode == FP_OK) { while(filerecvd < resp.filelen) { bytesrcvd = recv(∗sock, buffer, BUFSIZE−1, 0); if(bytesrcvd <= 0) { fprintf (stderr, "receiving file failed\n"); return −1; } buffer[bytesrcvd] = ’\0’; fprintf (stdout, "%s", buffer); filerecvd += bytesrcvd; } } return 0; } 4-10 Entwickler/User−Space 4.2 TCP/IP-Stack Web−Browser, E−Mail,. Anwendung Andere Anwendungen (erfordern spezielle Optimierung) Appl.−Protokolle: FTP, HTTP, SMTP, ... Andere Anwendungen Middleware: CORBA, RMI Programming Interface (Sockets) Betriebssystem TCP IGMP ICMP RARP ARP UDP Transport RIP IP OSPF Vermittlung Ethernet WLAN ... ATM Netzzugang 4-11 TCP/IP: Transportschicht Aufgabe der Transportschicht: Datentransport zwischen Prozessen Zwei Transportprotokolle im TCP/IP-Stack: UDP - User Datagram Protocol Unzuverlässige Kommunikation, kein Verbergen der zugrundeliegenden IP-Unzuverlässigkeiten Protokollentwickler muss selbst Mechanismen zu Erreichen der gewünschten Zuverlässigleit implementieren TCP - Transmission Control Protocol Expliziter Verbindungsaufbau Erhält Absendereihenfolge von Daten Liefert Daten garantiert aus Welches Protokoll man einsetzt hängt von der Anwendung ab 4-12 Transportschicht: UDP-Header 0 1234 567 89 01 234 567 8901 234 5678 9 01 Quell−Port Ziel−Port Länge Prüfsumme Daten . . . 4-13 Transportschicht: TCP-Header 0 12 34 56 7 89 01 23 45 67 89 0 12 34 56 78 90 1 Quell−Port Ziel−Port Sequenznummer Bestätigungsnummer Offset nicht verw. 1 2 3 4 5 6 Prüfsumme Fenster Dringlich Optionen Füllbytes Daten . . . 1 URG 2 ACK 3 PSH 4 RST 5 SYN 6 FIN 4-14 Transportschicht: TCP-Zustandsautomat CLOSED EINGABE/AUSGABE (Anwendungsbefehlle) (passive open)/ (active open)/SYN timeout/RST LISTEN SYN/SYN,ACK (send data)/SYN RST/ (close) SYN/SYN,ACK SYN RECVD timeout SYN,ACK/ACK ACK/ ESTABLISHED (close)/FIN SYN SENT FIN/ACK CLOSE WAIT (close)/FIN (close)/FIN FIN WAIT−1 FIN/ACK CLOSING LAST ACK ACK/ FIN WAIT−2 FIN,ACK/ACK FIN/ACK ACK/ ACK/ TIME WAIT timeout 4-15 Transportschicht: TCP-Verbindungsaufbau 3-way handshake“: ” (active open) CLOSED SYN−SENT SEQ=100 CTL=SYN CLOSED LISTEN (passive open) ESTABLISHED SEQ=300 ACK=101 CTL=SYN,ACK SYN−RECVD SEQ=101 ACK=301 CTL=ACK DATA ESTABLISHED 4-16