i

Einen Client zu einem Geburtstagsserver programmieren

Geburtstagsclient und Geburtstagsserver

In wie vielen Tagen hast du Geburtstag? Es gibt bereits einen Server, der dies berechnen kann. In diesem Kapitel programmieren wir einen Client zu diesem Server. Dazu muss der Server natürlich Tag und Monat deines Geburtsdatums wissen. Nach dem Verbindungsaufbau schickt der Client deshalb das Geburtsdatum an den Server. Anschließend antwortet der Server:

Beispiel für ein Anfrage

Umwandeln des Geburtsdatum in ein Bytes-Objekt

Auf der Seite Anfragen an einen Server stellen hast du gesehen, wie man eine Verbindung zu einem Server aufbaut. Dabei erhält man ein Socket-Objekt komm_s. Mit der Methode komm_s.sendall(datenAlsBytesObjekt) kann man Daten an den Server senden. Als Parameter erwartet diese Methode eines Bytes-Objekt. Ein Bytes-Objekt verwaltet eine Liste von Bytes - d.h. also eine Liste von Zahlen zwischen 0 und 255.

Aufgabe 1

(a) Probiere den folgenden Python-Dialog aus:
>>> # Ein Bytes-Objekt kann man mit Hilfe einer Liste erzeugen.     
>>> liste = [10, 20, 30, 255, 0]
>>> bytesObj = bytes(liste)

>>> # Um sich den Inhalt des bytes-Objekts anzeigen zu lassen, 
>>> # kann man es wieder in eine Liste umwandeln:
>>> list(bytesObj)
[10, 20, 30, 255, 0]
(b) Probiere den folgenden Python-Dialog aus und beschreibe, wodurch sich eine Liste und ein Bytes-Objekt unterscheiden. Tipp: Achte darauf, welche Werte in einer Liste bzw. in einem Byte-Objekt gespeichert werden können.
>>> liste1 = [4123]
>>> bytesObj1 = bytes(liste1)

>>> liste2 = ['Hallo']
>>> bytesObj2 = bytes(liste2)

Der Geburtstagsserver erwartet, dass der Client das Geburtsdatum als Zeichenkette (String) sendet. Dies erkennt man in dem Beispiel daran, dass das Geburtsdatum in Hochkomma steht: '14.3.' Wir müssen die Zeichenkette also zunächst in ein Bytes-Objekt umwandeln. Man könnte dazu den ASCII-Zeichensatz verwenden. Da im ASCII-Zeichensatz keine Umlaute vorhanden sind, verwenden wir utf-8.

Aufgabe 2

ASCII ordnet jedem Zeichen der englischen Sprache eine Zahl zwischen 0 und 255 (d.h. also ein Byte) zu. Ordnet utf-8 ebenfalls jedem Zeichen genau ein Byte zu? Probiere den folgenden Python-Dialog aus, um dies herauszufinden:
>>> zeichenkette1 = 'Hallo'
>>> # Zeichenkette mit Hilfe von utf-8 in ein Bytes-Objekt umwandeln:
>>> bytesObjekt1 = bytes(zeichenkette1, 'utf-8')
>>> # Zahlen im Bytes-Objekt anzeigen lassen:
>>> list(bytesObjekt1)
[72, 97, 108, 108, 111]

>>> zeichenkette2 = 'ä'
>>> bytesObjekt = bytes(zeichenkette, 'utf-8')
>>> list(bytesObjekt)
[195, 164]

Der Client schickt das Geburtsdatum an den Server

Das folgende Beispiel zeigt, wie eine Zeichenkette gesendet werden kann:

datenStr = 'Ich bin ein String!'
datenBytes = bytes(zeichenkette, 'utf-8')
komm_s.sendall(datenBytes)

trennByte = bytes([0])
komm_s.sendall(trennByte)

Der Befehl trennByte = bytes([0]) erzeugt ein Bytes-Objekt, das nur ein Byte mit dem Wert 0 enthält. Mit komm_s.sendall(trennByte) senden wir dieses Bytes-Objekt. Damit zeigen wir dem Server, dass wir unsere gesamte Zeichenkette gesendet haben. Anschließend kann der Server antworten.

Da wir die Codeschnipsel aus dem letzten Beispiel oft benötigen, packen wir sie in zwei Funktionen:

def sendeStr(komm_s, datenStr):
    datenBytes = bytes(datenStr, 'utf-8')
    komm_s.sendall(datenBytes)

def sendeTrennByte(komm_s):
    trennByte = bytes([0])
    komm_s.sendall(trennByte)

Aufgabe 3

Server dieser Aufgabe: geburtstagsserver.py

(a) Schreibe ein Python-Programm, das

  • eine Verbindung zu dem Geburtstagsserver aufbaut,
  • den Tag und Monat deines Geburtsdatums an den Server schickt und
  • das Trennbyte an den Server schickt.

Verwende dabei die Funktionen sendeStr(komm_s, datenStr) und sendeTrennByte(komm_s). Du kannst sie aus der Datei socketLib.py importieren:

from socketLib import sendeStr, sendeTrennByte

(b) Ändere dein Programm aus a) so ab, dass das Programm den Benutzer zunächst nach seinem Geburtsdatum fragt.

Der Client empfängt die Antwort des Servers

Mit dem Befehl neueDaten = komm_s.recv(1) können wir Daten empfangen und in die Varibale neueDaten übertragen. Der Parameter 1 zeigt an, dass wir 1 Byte empfangen möchten. Wir müssen wir komm_s.recv(1) mehrmals aufrufen, bis wir

  • entweder das Byte 0 erhalten. Damit zeigt der Server an, dass er seine gesamte Nachricht gesendet hat
  • oder ein leeres Bytes-Objekt erhalten. Daran erkennen wir, dass der Server die Verbindung geschlossen hat.

Dazu kannst du in deinen Programmen folgende Funktion verwenden:

# Liest Daten, bis der Sender anzeigt,
# dass er keine weiteren Daten schicken wird
# oder bis die Verbindung vom Sender geschlossen wird.
# Parameter: Socket-Objekt komm_s, von dem gelesen werden soll
# Rückgabewert: gelesene Daten als String (Kodierung utf-8)
def empfangeStr(komm_s):
    weiter = True
    datenBytes = bytes()

    trennByte = bytes([0])

    while weiter:
        chunk = komm_s.recv(1)
        if chunk == trennByte or chunk == bytes([]):
            weiter = False
        else:
            datenBytes = datenBytes + chunk

    datenStr = str(datenBytes, 'utf-8')

    return datenStr

Die Methode komm_s.recv(1) gibt ein Bytes-Objekt zurück. Der folgende Python-Dialog zeigt, wie ein Bytes-Objekt wieder in eine Zeichenkette umgewandelt werden kann:

>>> bytesObj = bytes([72, 105])
>>> str(bytesObj, 'utf-8')
'Hi'

Die Funktion empfangeStr(komm_s) übernimmt diese Umwandlung bereits für uns.

Aufgabe 4

Server dieser Aufgabe: geburtstagsserver.py

Erweitere dein Programm aus Aufgabe aus Aufgabe 3, so dass die Antwort des Servers empfangen und ausgegeben wird. Verwende die Funktion empfangeStr(komm_s), die du ebenfalls aus der Datei socketLib.py importieren kannst.

Beenden der Verbindung

Wenn wir den Kommunikationssocket komm_s nicht mehr benötigen, müssen wir ihn schließen:
komm_s.close()

Aufgabe 5

Server dieser Aufgabe: geburtstagsserver.py

Erweitere dein Programm aus Aufgabe aus Aufgabe 4, so dass der Kommunikationssocket geschlossen wird.

Suche

v
10.5.4.3
inf-schule.de/rechnernetze/anwendung/socketprogrammierung/Client_zu_einem_Geburtstagsserver
inf-schule.de/10.5.4.3

Rückmeldung geben