Exkurs - Funktionsweis der socketLib
Auf dieser Seite wird erklärt, wie die Funktionen sendeStr, empfangeStr und sendeTrennByte funktionieren. Du musst diese Seite nicht gelesen haben, um die folgenden Seiten zu bearbeiten.
Ein Kommunikationssocket komm_s
besitzt die Methoden komm_s.sendall(datenAlsBytesObjekt)
und komm_s.recv(anzahlBytes)
zum Senden und Empfangen von Daten.
Die Arbeit mit diesen Methoden ist schwierig. Deshalb verwenden wir die Funktionen aus der socketLib. Sie verwenden intern auf die Methoden des Kommunikationssockets.
Zeichenketten und Bytes-Objekte
Die Methode komm_s.sendall(datenAlsBytesObjekt)
akzeptiert als Parameter ein Bytes-Objekt.
Ein Bytes-Objekt verwaltet eine Liste von Bytes (d.h. von Zahlen zwischen 0 und 255).
Möchte man eine Zeichenkette senden, muss man diese also zunächst in ein Bytes-Objekt umwandeln:
>>> zeichenkette = 'Hallo'
>>> # Zeichenkette umwandeln in ein Bytes-Objekt:
>>> bytesObjekt = bytes(zeichenkette, 'utf-8')
>>> # Bytes als Zahlen zwischen 0 und 255 anzeigen lassen:
>>> list(bytesObjekt)
[72, 97, 108, 108, 111]
Die Methode komm_s.recv(1024)
liefert also Rückgabewert ebenfalls ein Bytes-Objekt.
Dieses Bytes-Objekt kann man wieder in eine Zeichenkette umwandeln:
>>> # Bytes-Objekt erzeugen:
>>> bytesObjekt = bytes('[72, 97, 108, 108, 111])
>>> # Bytes-Objekt in eine Zeichenkette umwandeln
>>> zeichenkette = str(bytesObjekt, 'utf-8')
>>> zeichenkette
>>> 'Hallo'
Daten senden
Die Funktion sendeStr(komm_s, zeichenkette) erhält als Parameter eine Zeichenkette, die gesendet werden soll.
Sie muss also zunächst in ein Bytes-Objekt umgewandelt werden.
Quelltext der Funktion sendeStr:
def sendeStr(komm_s, datenStr):
datenBytes = bytes(datenStr, 'utf-8')
komm_s.sendall(datenBytes)
Anzeigen, dass (im Moment) keine weiteren Daten gesendet werden
Der Geburtstagsserver aus Client zu einem Geburtstagsserver benötigt das Geburtsdatum des Benuters. Deshalb muss der Client zunächst das Geburtsdatum an den Server schicken. Woran erkennt der Server, dass der Client das gesamte Geburtsdatum übertragen wurde? Es gibt mehrere Möglichkeiten, wie man dieses Problem lösen könnte. Bei unseren Programm schicken wir immer das Byte 0 um anzuzeigen, dass wir im Moment keine weiteren Daten schicken möchten. Diese Aufgabe übernimmt die Funktion sendeTrennByte:
def sendeTrennByte(komm_s):
trennByte = bytes([0])
komm_s.sendall(trennByte)
Bei der Umwandlung einer Zeichenkette in ein Bytes-Objekt verwenden wir die Umwandlungstabelle utf-8. Das Byte 0 wird in dieser Tabelle nicht für ein Zeichen verwendet. Deshalb kann das Trennbyte nicht mit einem Byte, das zu einem Zeichen gehört, verwechselt werden.
Daten empfangen
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.
# 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