client sending während client receives

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Benutzeravatar
Finux
User
Beiträge: 32
Registriert: Mittwoch 18. September 2019, 13:59

Hallo,

hoffe es sorgt nicht für Unmut, aber wollte euch ja auf dem Laufenden halten :)

Vom Kollegen wurden mir heute 2 wichtige Fragen zum Code gestellt:
1. Kann der Client denn etwas senden wenn er gerade Daten empfängt? --> ja, das kann er!
2. Wann arbeitet der Server mit receive? --> und da wurde mir klar, warum der Server einen evtl. nachgelieferten Befehl erst nach seiner "aktuellen Aufgabe" sendet. :]

Damit wäre meine Ursprungsfrage "Wieso kann ich während dem Empfangen auf der Client-Seite nichts senden?" endlich geklärt. Ich habe die Struktur demnach auf der server.py etwas umgebaut. Hier steht das receive in seinem eigenen "client-thread" wie gewohnt ganz oben, sobald aber eine Funktion aufgerufen+gesendet werden soll mache ich hier einen eigenen Thread dafür auf. Es funktioniert (im localhost) ohne Probleme.

Eine Kontrollmöglichkeit zur Prüfung ob eine Verbindung noch besteht werde ich ebenso noch einbauen.

Das Thema "Passworthashing" werde ich mir in Ruhe nochmal anschauen, hat derzeit allerdings keine Priorität.

Nochmal zu dem mir unangenehmen Thema "Protokoll":
Ich werde (wenn es mir die Zeit erlaubt) vom Sender vor der eigentlichen Message eine feste Bytelänge an den Empfänger übertragen. Erst dann sende ich, was ich eigentlich senden wollte. Stimmt beim Empfänger die Länge der emfangenen Pakete z.B. mit der Bytelänge überein, weiß ich dass das Paket nun weiterverarbeitet werden darf, da es komplett ist. Ist es das nicht, teile ich dem Sender mit, dass er alles noch einmal schicken soll. Usw. usw.

Seid nicht stressed, ich glaube ich habe ein paar sehr gute Dinge daraus gelernt, auch wenn ich noch weit entfernt von einem soliden Programm bin, aber dafür muss ich eben Fehler machen und Fragen stellen :)
Nochmals Danke, dass ihr euch die Zeit genommen habt.

LG
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

@Finux: nochmal die Frage, warum Du alles selbst machen willst, statt gut getestete bewährte Bibliotheken mit Standardprotokollen zu verwenden?

Dass Dein ›nochmal schicken‹ nicht gerade die intelligenteste Lösung ist, weißt Du hoffentlich selbst.
Statt dessen einfach so lange lesen, bis Du genug Bytes zusammen hast:

Code: Alles auswählen

def recv_bytes(socket, length):
    data = b''
    while len(data) < length:
        data += socket.recv(length - len(data))
    return data

def recv_packet(socket):
    length = int.from_bytes(recv_bytes(socket, 8), 'little'))
    return recv_bytes(socket, length)

def send_packet(socket, data):
    socket.sendall(len(data).to_bytes(8, 'little'))
    socket.sendall(data)
Benutzeravatar
Finux
User
Beiträge: 32
Registriert: Mittwoch 18. September 2019, 13:59

@Sirius3: Die Kollegen sind nicht sehr überzeugt von Standardlibrarys, nativ ist zwar aufwendiger, aber man weiß "recht genau" was man hier tut ohne sich auf "Fremdwerke" verlassen zu müssen. Ein Kollege ist allerdings auch der Meinung, dass man mit Standardbibliotheken gut zurecht käme... daher der ganze Aufwand.
Danke für den Code! Den saug ich mir morgen in aller Ruhe mal in den Kopf! :)
__deets__
User
Beiträge: 14541
Registriert: Mittwoch 14. Oktober 2015, 14:29

Sich gegen mitgelieferte Standards stellen, aber dann mit threading und mangelndem know-how was zusammenzimmern - 🤦‍♂️

Wieso ist das mitgelieferte socket-Modul denn koscher, aber das mitgelieferte urllib und HTTPServer nicht? Das muss man nicht verstehen, oder?

Ich weiss das es nicht deine Schuld ist. Aber sowas ist wirklich hirnverbrannt. Man muss es ja nicht treiben wie die JS-Community, bei der leicht hunderte Abhaengigkeiten fuer ein triviales Projekt zusammenkommen. Aber jeden Morgen den Feuerstein aus dem Steinbruch brechen, und sich ein Rad zimmern muss es ja nun auch nicht sein. Vor allem nicht in Python, das schon so viel mitbringt.
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

Du weißt eben nicht recht genau, was Du hier tust. Mit diesem Argument darfst Du Dich auch nicht auf dieses sockets und den darunterliegenden C-Routinen verlassen. Da weiß man ja nicht, was passiert. An Deiner Stelle würde ich auch auf das völlig undurchsichtige Betriebssystem verzichten und den Maschinencode direkt im Hex-Editor schreiben, wer weiß schon, was da ein sogenannter Compiler aus meinem schönen Code macht.
Benutzeravatar
__blackjack__
User
Beiträge: 13110
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Finux: Das Problem hier ist das sowohl Sockets als auch Threads/nebenläufige Programmierung *komplex* sind, und das man ganz leicht Fehler machen kann, die aber nicht auffallen, weil scheinbar alles funktioniert. Es ist bei beiden nicht so das man was falsch macht und bei gleichem Code und gleichen Daten bei jedem Programmlauf die gleichen falschen Daten als Ergebnis kommen oder immer an der gleichen Stelle eine Ausnahme. Man kann auch ”immer” das richtige Ergebnis bekommen bei jedem Programmlauf. Die Anführungszeichen bei ”immer”, weil es eben nicht immer ist. Vielleicht sogar recht selten. Vielleicht in der Hard- und Software-Konstellation die man verwendet sogar nie. Es ist dann aber trotzdem fehlerhaft.

Wenn man hier eine Bibliothek verwendet, wo sich jemand der schon gut programmieren kann, Gedanken über den Code gemacht hat, und der schon von ganz vielen Leuten, schon lange und erfolgreich in Projekten eingesetzt wurde, dann kann das nur besser sein. Wer da meint man könne sich nicht auf fremde Bibliotheken verlassen, und das dann lieber selbst zusammenzimmert hat ziemlich einen an der Waffel. Und meistens sind das die Leute die denken sie könnten das alles, und da dann selbst Code mit mehr oder weniger subtilen Fehlern produzieren.

Darum sagen Dir hier mehrere erfahrene Programmierer: Mach das nicht selbst. Ich selbst würde mir das nicht so ohne weiteres zutrauen, weil ich immer Angst hätte irgend etwas zu vergessen. Und man muss im Grunde auch immer für die andere Seite einer Verbindung mitdenken, was die falsch machen könnte. Bei Sirius3's `recv_bytes()`-Code ist mir beispielsweise als erstes aufgefallen das die Gegenseite ihr Ende der Verbindung nicht zumachen darf, denn dann liefert `socket.recv()` bei jedem Aufruf 0 Bytes und das ist eine Endlosschleife.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten