Schnittstelle Client <> Server einrichten

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
MajorPayne
User
Beiträge: 13
Registriert: Freitag 7. Oktober 2016, 09:56

Hallo liebe Forengemeinde,

ich bin ein Neuling hier und hoffe das ihr mir bei meinem Problem helfen könnt.
Ich denke, dass ich ein bisschen auf dem Schlauch stehe und nur einen kleinen anstupser brauche :lol:
Da ich selbst in anderen Foren aktiv bin weiß ich, dass es für euch leichter ist mir zu helfen wenn ich mein Problem so genau wie möglich beschreibe.

Also zu meinem Problem:
Ich möchte eine Ethernet Verbindung zwischen meinem PC (Client) und einem weiteren Gerät (Server) herstellen.
Der Server bietet verschiedene Dienste, die ich nutzen möchte. Hier ist zu sehen, wie ein Telegramm aussehen muss, um zum Beispiel den Dienst nutzen zu können virtuelle Ein- bzw. Ausgänge auslesen zu können.

Bild

Soweit so gut. Ich habe mir dann mal ein Tool runtergeladen (TCP Test Tool) um eine solche Anforderung mal zu stellen. Es stimmen zwar nicht alle Bytes mit den Erwartungen überein ABER das sieht schon mal sehr gut aus.

Bild

Nun versuche ich ein kleines Python Programm zu schreiben, welches ebenfalls eine Anforderung senden und empfangen soll. Im Weiteren möchte ich diese Daten dann weiterverarbeiten.
Hier mein kleines Programm:

Code: Alles auswählen

import socket

n0 = '0x05'
n1 = '0x15'
n2 = '0x00'
n3 = '0x05'
n4 = '0x2C'
n5 = '0x00'
n6 = '0x01'
n7 = '0x00'
n8 = '0xD3'
n9 = '0x10'


ip = '169.254.60.1'
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)   # AF_INET und SOCK_STREAM für einen TCP Socket
print "socket created"
s.connect((ip, 9000))
print "Your are connected to PNOZ m B1 with IP adress of %s"%(ip)


try: 
    #while True:
        s.send(n0)
        s.send(n1)
        s.send(n2)
        s.send(n3)
        s.send(n4)
        s.send(n5)
        s.send(n6)
        s.send(n7)
        s.send(n8)
        s.send(n9)  
            
        antwort = s.recv(252) 
        print "[%s] %s" % (ip,antwort) 
finally: 
    s.close()
Führe ich das Programm nun aus so erhalte ich weder bei der Erstellung des Sockets noch beim Verbindungsaufbau (connect) eine Exception. Daher gehe ich davon aus, dass die Verbindung zum Server steht. Leider stürzt die Python Shell anschießend ab und ich kann sie nur noch zwingen sich zu schließen. Eine empfangende Antwort wird nicht mehr ausgegeben.

Ich hoffe ihr seht meinen Fehler und könnt mir helfen.

Vielen Dank und freundliche Grüße!
Markus
Zuletzt geändert von Anonymous am Freitag 7. Oktober 2016, 11:09, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

@MajorPayne: Die lustige Welt der Socket-Programmierung. Wo alles irgendwie umständlich ist und fehlerhafte Programme laufen können, bis sie dann endlich mal über den Fehler stolpern. :-)

Erst einmal, was heisst abstürzen? Die Beschreibung klingt eher nach hängen bleiben. Und wirklich *hart* oder kann man das Programm eventuell doch ”sanft(er)” beenden als den Prozess vom Betriebssystem abzuschiessen? Was hast Du probiert? <Strg>+<C> bricht das Programm nicht ab? Hast Du mal `print`-Anweisungen eingefügt um zu sehen was noch ausgeführt wird, also ob es schon bei den `send()`-Aufrufen hängt oder erst beim `recv()`?

Da kommen wir dann auch schon zu den lustigen Eigenschaften dieser beiden Methoden. So wie Du das geschrieben hast, ist weder garantiert das die Daten alle gesendet werden, noch das die Antwort komplett empfangen wird.

`send()` kann laut Spezifikation weniger senden als man übergeben hat. Also in diesem Fall auch 0 Bytes von dem einen Byte was jeweils übergeben wurde. Die Methode gibt die Anzahl der gesendeten Bytes zurück und man muss in einer Schleife solange immer wieder den verbleibenden Rest senden bis wirklich alles übergeben werden konnte. Netterweise braucht man diese Schleife nicht selbst schreiben, sondern kann die `sendall()`-Methode verwenden. Die macht das schon.

`recv()` empfängt mindestens ein Byte und maximal so viele wie man als Argument übergeben hat. Man muss das also, so ähnlich wie bei `send()` so lange aufrufen bis man mindestens seine komplette Nachricht beisammen hat, denn im Extremfall kann jeder Aufruf auch nur *ein* Byte aus dem Datenstrom liefern. Andererseits, kann es bei einer grösseren Angabe von Bytes die empfangen werden sollen, auch solange blockieren bis die alle angekommen sind, oder zumindest bis eine Zeitüberschreitung auftritt. Von der man so allerdings erst einmal nicht sagen kann wie lange die dauert. Da das Beispiel aus der Dokumentation deutlich weniger als 252 Bytes als Antwort beschreibt, kann es sein, dass das Programm hier einfach hängt weil es auf mehr Daten wartet als da kommen.

Was auch noch passieren kann, zumindest bei Terminals/Terminalemulatoren ist dass das läuft, aber die Binärdaten die da einfach 1:1 ausgegeben werden das Terminal in einen ”komischen” Zustand versetzen, so dass es so aussieht als würde das Programm nicht mehr laufen, und das Terminal nicht mehr für Eingaben benutzbar sein. Die Ausgabe der Binärdaten würde man besser als `repr()`-Darstellung machen oder in eine Hexadezimaldarstellung umwandeln (siehe das `binascii`-Modul).

Argh. Und *jetzt* sehe ich gerade das die Daten die gesendet werden falsch sind. Die `n*`-Namen sollten jeweils an *einen* Bytewert gebunden werden, also an eine ”Zeichen”kette der Länge 1 wo das ”Zeichen” den Bytewert besitzt der gesendet werden soll. '0x05' enthält aber vier Bytes und zwar die ASCII-Werte für 0, x, 0, und 5. Du möchtest an der Stelle aus der 0 einen \ machen:

Code: Alles auswählen

In [1]: import binascii

In [2]: '0x05'
Out[2]: '0x05'

In [3]: len('0x05')
Out[3]: 4

In [4]: list('0x05')
Out[4]: ['0', 'x', '0', '5']

In [5]: '\x05'
Out[5]: '\x05'

In [6]: len('\x05')
Out[6]: 1

In [7]: list('\x05')
Out[7]: ['\x05']

In [8]: binascii.b2a_hex('\x05')
Out[8]: '05'

In [9]: binascii.b2a_hex('\x05\x15\x00\x05')
Out[9]: '05150005'
Wie man sieht musst Du auch nicht die einzelnen Bytes jeweils an einen Namen binden, sondern man kann auch eine ”Zeichen”kette mit allen Bytes angeben.

*Vorsicht*: Auch wenn das dann mit ansonsten unverändertem Quelltext funktionieren sollte, die ganzen anderen Punkte gelten trotzdem. Das würde dann nur zufällig funktionieren, kann aber jederzeit über die Eigenheiten von `send()` und `recv()` stolpern!

Am einfachsten wird es wenn man sich von dem Socket-Objekt mit der `make_file()`-Methode ein Dateiobjekt geben lässt, denn `read()` und `write()` auf Python's Dateiobjekten garantieren das alle Daten geschrieben werden (oder eine Ausnahme ausgelöst wird wenn das nicht geht), und die angegebene Anzahl von Bytes gelesen werden (sofern sie vorhanden sind, also weniger wenn vorher das Dateiende erreicht wird).

Namen durchnummerieren ist übrigends ein „code smell“. An der Stelle möchte man eigentlich eine Datenstruktur verwenden. Oft ist das eine Liste.
Benutzeravatar
pillmuncher
User
Beiträge: 1532
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

BlackJack hat geschrieben:Namen durchnummerieren ist übrigends ein „code smell“.
...that smelly smell...
In specifications, Murphy's Law supersedes Ohm's.
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

man könnte doch aber auch

Code: Alles auswählen

bytes = [0x05, 0x15, 0x00, 0x05, 0x2C, 0x00, 0x01, 0x00, 0xD3, 0x10]
...
...
for byte in bytes:
    s.send(chr(byte))
...
...
empty Sig
BlackJack

@harryberlin: Könnte man wenn man aus dem `send()` ein `sendall()` macht, denn sonst hat man wieder/immer noch das Problem, dass die Bytes nicht gesendet werden müssen. Allerdings wird hier der eingebaute Datentyp `bytes` an einen anderen Wert gebunden. In Python 2.7 ist das nur ein Alias auf `str`. Man könnte aber wenn man die Daten in der Form, einer Liste mit Bytewerten, vorliegen hat den Typ `bytearray` verwenden und sich die Schleife sparen:

Code: Alles auswählen

    values = bytearray(
        [0x05, 0x15, 0x00, 0x05, 0x2C, 0x00, 0x01, 0x00, 0xD3, 0x10]
    )
    ...
    ...
    sock.sendall(values)
    ...
    ...
Das funktioniert dann in Python 2 und 3.
BlackJack

Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python
# coding: utf8
from __future__ import absolute_import, division, print_function
import socket
from binascii import b2a_hex
from contextlib import closing


def main():
    telegram = bytearray(
        [0x05, 0x15, 0x00, 0x05, 0x2C, 0x00, 0x01, 0x00, 0xD3, 0x10]
    )
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect(('169.254.60.1', 9000))
    with closing(sock):
        connection = sock.makefile()
        connection.write(telegram)
        response = connection.read(42)
    print(b2a_hex(response))

 
if __name__ == '__main__':
    main()
MajorPayne
User
Beiträge: 13
Registriert: Freitag 7. Oktober 2016, 09:56

Guten Morgen!

Zunächst mal vielen Dank für eure teils sehr ausführlichen Antworten!

Ich hatte ganz vergessen zu erwähnen, dass ich Python 2.3.4 benutze. Das hat den Hintergrund, dass die Zielplattform auf der das Programm später laufen soll, mindestens diese Python Version oder eine jüngere besitzt. Wegen der Aufwärtskompatibilität, was die Python Version angeht, muss ich mir keine Sorgen machen, oder? :K
BlackJack hat geschrieben:Erst einmal, was heisst abstürzen?
Mit Strg +C ließ sich das Programm nicht beenden. Ich musste immer den Windows Prozess beenden.
Ich hatte zwischendurch noch ein print() Befehl zwischen die send() und recv() Anweisung gesetzt. Diese wird noch ausgeführt, erst danach also beim recv() blieb das Programm hängen.
BlackJack hat geschrieben:`send()` kann laut Spezifikation weniger senden als man übergeben hat. Also in diesem Fall auch 0 Bytes von dem einen Byte was jeweils übergeben wurde. Die Methode gibt die Anzahl der gesendeten Bytes zurück und man muss in einer Schleife solange immer wieder den verbleibenden Rest senden bis wirklich alles übergeben werden konnte. Netterweise braucht man diese Schleife nicht selbst schreiben, sondern kann die `sendall()`-Methode verwenden. Die macht das schon.

`recv()` empfängt mindestens ein Byte und maximal so viele wie man als Argument übergeben hat. Man muss das also, so ähnlich wie bei `send()` so lange aufrufen bis man mindestens seine komplette Nachricht beisammen hat, denn im Extremfall kann jeder Aufruf auch nur *ein* Byte aus dem Datenstrom liefern. Andererseits, kann es bei einer grösseren Angabe von Bytes die empfangen werden sollen, auch solange blockieren bis die alle angekommen sind, oder zumindest bis eine Zeitüberschreitung auftritt. Von der man so allerdings erst einmal nicht sagen kann wie lange die dauert. Da das Beispiel aus der Dokumentation deutlich weniger als 252 Bytes als Antwort beschreibt, kann es sein, dass das Programm hier einfach hängt weil es auf mehr Daten wartet als da kommen.
Danke für diese Hinweise. Werde ich in Zukunft beachten. Ich hatte mein Programm mit dem Buch "Python 3" vom Rheinwerk Computing erstellt und bin dabei nicht auf dieses Problem gestoßen -.-.
Bei den 252 Bytes hatte ich mich geirrt. Dort müssten natürlich 42 Bytes aufgezeichnet werden, so wie es im Handbuch steht.
BlackJack hat geschrieben:Am einfachsten wird es wenn man sich von dem Socket-Objekt mit der `make_file()`-Methode ein Dateiobjekt geben lässt, denn `read()` und `write()` auf Python's Dateiobjekten garantieren das alle Daten geschrieben werden (oder eine Ausnahme ausgelöst wird wenn das nicht geht), und die angegebene Anzahl von Bytes gelesen werden (sofern sie vorhanden sind, also weniger wenn vorher das Dateiende erreicht wird).
Super Sache! Ich bin gerade am recherchieren um mehr über diesen Ansatz zu lernen.
BlackJack hat geschrieben:Namen durchnummerieren ist übrigends ein „code smell“.
Das ist mir bewusst. :oops:
Das Programm sollte wirklich nur ein grober Entwurf sein um überhaupt erstmal einen Einstieg in die Socket-Programmierung zu bekommen deshalb hatte ich auf den code style nicht geachtet.


Vielen Dank für den Programmentwurf BlackJack! Ich werde das nachher mal testen und dann berichten.

Freundliche Grüße
Markus
MajorPayne
User
Beiträge: 13
Registriert: Freitag 7. Oktober 2016, 09:56

Hallo nochmal :)

BlackJack ich habe gerade versucht dein Programm laufen zu lassen. Dabei habe ich folgende Fehlermeldung bekommen.

Bild

Kann es sein, dass der Befehl der Python Version 2.3.4 noch nicht zur Verfügung steht?

Freundliche Grüße
Markus
Zuletzt geändert von MajorPayne am Montag 10. Oktober 2016, 10:02, insgesamt 2-mal geändert.
Sirius3
User
Beiträge: 18335
Registriert: Sonntag 21. Oktober 2012, 17:20

@MajorPayne: Version 2.3 ist nun ja schon sehr alt. Woher kommt denn die Anforderung, dass so eine alte Version noch unterstützt werden muß? Vor allem, weil das ja scheinbar unter Windows läuft und dort sowieso extra Python installiert werden muß und damit ohne weiteres eine neuere Version genommen werden kann.

Strg+C wird in Python nur zwischen zwei Befehlen abgefragt und damit hängt das Programm, bis recv irgendwie abbricht. Ohne Timeout ist das nie.

Die meisten allgemeinen Python-Bücher gehen auf Socket-Programmierung nicht wirklich ein. Da wird nur der falsche Schrott wiederholt, den man überall findet. Mir hat zum Verstehen von Sockets das Buch "Advanced UNIX Programming" von 1990 geholfen, weil es so schön aktuell ist.
MajorPayne
User
Beiträge: 13
Registriert: Freitag 7. Oktober 2016, 09:56

Hallo Sirius!
Vielen Dank für deine sehr schnelle Antwort:)
Sirius3 hat geschrieben:@MajorPayne: Version 2.3 ist nun ja schon sehr alt. Woher kommt denn die Anforderung, dass so eine alte Version noch unterstützt werden muß? Vor allem, weil das ja scheinbar unter Windows läuft und dort sowieso extra Python installiert werden muß und damit ohne weiteres eine neuere Version genommen werden kann.
Das ist wohl wahr. Die Anforderung kommt daher, dass das Programm auf einer CNC Steuerung laufen und eingebunden werden soll. Genauer gesagt ist es eine CNC Steuerung der Firma Heidenhain und diese besitzen diese alten Softwarestände.

Japp das ist richtig. Ich habe das Programm aktuell unter Windows laufen. Dafür habe ich eben extra die 2.3 heruntergeladen. Es ist einfacher für mich mein Programm mal schnell unter Windows zu testen als es zunächst in der Steuerung einbinden zu müssen.
Sirius3 hat geschrieben:Die meisten allgemeinen Python-Bücher gehen auf Socket-Programmierung nicht wirklich ein. Da wird nur der falsche Schrott wiederholt, den man überall findet. Mir hat zum Verstehen von Sockets das Buch "Advanced UNIX Programming" von 1990 geholfen, weil es so schön aktuell ist.
Das kenn ich nur zu gut! Ich studiere zur Zeit Informations- und Elektrotechnik und wenn ich dort gute Literatur finde ist die meist auch schon 20 Jahre alt xD

Freundliche Grüße
Markus
MajorPayne
User
Beiträge: 13
Registriert: Freitag 7. Oktober 2016, 09:56

MajorPayne hat geschrieben:Hallo nochmal :)

BlackJack ich habe gerade versucht dein Programm laufen zu lassen. Dabei habe ich folgende Fehlermeldung bekommen.

Bild

Kann es sein, dass der Befehl der Python Version 2.3.4 noch nicht zur Verfügung steht?

Freundliche Grüße
Markus

Ich weiß leider nicht wie man Beiträge zu einem späteren Zeitpunkt noch editiert. Den "with closing(sock)" befehl hatte ich ausgetauscht durch den normalen sock.close(), da ich durch das "closing" ein Syntax Error hatte. Kann es sein, dass das ebenfalls mit der Python Version zu tun hat?
Sirius3
User
Beiträge: 18335
Registriert: Sonntag 21. Oktober 2012, 17:20

@MajorPayne: viele Sprachkonstrukte wurden erst mit 2.5 oder 2.7 eingeführt. Wenn Du wissen willst, was alles nicht geht, solltest Du Dir die "What's new"-Seite durchlesen.
MajorPayne
User
Beiträge: 13
Registriert: Freitag 7. Oktober 2016, 09:56

Sirius3 hat geschrieben:@MajorPayne: viele Sprachkonstrukte wurden erst mit 2.5 oder 2.7 eingeführt. Wenn Du wissen willst, was alles nicht geht, solltest Du Dir die "What's new"-Seite durchlesen.
Danke Sirius! Habe die Seite mal durchgeblättert und festgestellt, dass viel brauchbares wirklich erst nach 2.3 eingeführt wurde. Hab daraufhin nochmal mit meinem Betreuer gesprochen. (Bei dem Projekt handelt es sich um eine Studienarbeit) Wir haben dann festgelegt, dass ich Python bis einschließlich der Version 2.7 benutzen kann was mir sehr entgegen kommt :)

Hab deshalb Python gestern noch neu aufgesetzt und BlackJacks Prog getestet.
Zunächst mal läuft es ohne Syntax Probleme und auch der Verbindungsaufbau funktioniert.

Dann habe ich jedoch das gleiche Problem wie vorher. Das Programm wartet nach dem Senden auf die Antwort und bleibt dabei hängen. Ich habe das durch print() Befehle getestet.

Da ich mir dieses Verhalten nicht erklären kann, habe ich Wireshark installiert um mir anschauen zu können was da vor sich geht.

Hier mal ein Ausschnitt, was da über die Ethernet Verbindung geschickt wird, sobald ich das Programm gestartet habe.

Bild

Der Server sendet alle 5 Sekunden etwas an den Client aber ich kann im Moment nicht ausmachen was es ist.
Wartet der Server auf einen weiteren Befehl?
Hat jemand Erfahrungen mit Wireshark und sieht da durch?

Freundliche Grüße
Markus
MajorPayne
User
Beiträge: 13
Registriert: Freitag 7. Oktober 2016, 09:56

Ein paar Tests zeigen, dass es mit BlackJacks Programm das gleiche Problem gibt wie mit meinem. Trotzdem bin ich die natürlich dankbar für die ganzen Hinweise.

Hier mal ein Ausschnitt aus Wireshark in Verbindung mit dem TCP Test Tool:

Bild

Dabei ist zu erkennen, dass zunächst via ARP die IP/Mac Adressvergabe geregelt und anschließend synchronisiert wird. An Punkt 3 kommt die "keepalive" Routine des Servers(ich gehe davon aus, dass das vom Server ausgeführt wird) ins Spiel und überprüft ob die Verbindung noch steht. An Punkt 4 hatte ich dann manuell eine Anfrage gesendet und direkt das Ergebnis bekommen. Das Ergebnis steht mit 42 byte in Data. Im Anschluss (5) trat die "keepalive" Routine wieder auf. An Punkt 6 habe ich die Verbindung manuell gekappt.


Den gleichen Ablauf wünsche ich mir natürlich mit dem Python Programm, wobei die langen Zeiten dazwischen natürlich nicht benötigt werden. Ich habe dazu einmal den connection.read() Befehl mal auskommentiert und ihn durch eine Wartezeit time.sleep(10) ersetzt. Hier ein Auszug der dabei entstehenden Kommunikation.

Bild

Wie man sieht findet die gleiche Kommunikation statt. Nur das hier das Datenpaket mit den für mich relevanten Infomationen fehlt. Da ich zwar das connection.read() rausgenommen habe aber trotzdem noch sende müsste das Paket doch trotzdem geschickt werden oder?


Ich werde diesbezüglich nochmal den Hersteller des Servers kontaktieren um abzuklären ob die Ansprache so in Ordnung ist oder nicht. Ich denke, dass da noch irgendetwas fehlt.

Freundliche Grüße
Markus
Sirius3
User
Beiträge: 18335
Registriert: Sonntag 21. Oktober 2012, 17:20

@MajorPayne: der interessantere Teil wäre ja der, wo Du die Daten sendest, um zu sehen, ob sie in beiden Fällen exakt gleich sind.
MajorPayne
User
Beiträge: 13
Registriert: Freitag 7. Oktober 2016, 09:56

@Sirius: Da hast du absolut recht. Leider weiß ich noch nicht wie ich da hinkomme. Die von mir gezeigten Kommunikationen sind nicht gefiltert (zumindest habe keine Filter aktiv gesetzt). Es sieht aber so aus als wären alle Datenpakete nur eingehende oder irre ich mich da?
MajorPayne
User
Beiträge: 13
Registriert: Freitag 7. Oktober 2016, 09:56

Guten Morgen!

Ich habe gestern mir gestern noch den Microsoft Network Monitor installiert um mir damit den Datenverkehr nochmal anschauen zu können.

Zunächst der Datenaustausch mit dem tcp test tool:

Anfrage an den Server:

Bild

Antwort vom Server:

Bild

Soweit so gut.


Nun das gleiche mit dem Python Programm.

Anfrage:

Bild

Der Anforderungscode ist dabei eindeutig zu erkennen (markiert). Das Telegramm unterscheidet sich soweit ich das beurteilen konnte nur in der Checksum, Sequenznummer usw. von dem des TCP Tools.

Hier die Antwort des Servers:

Bild

Dabei handelt es sich um ein "leeres" Telegramm. Damit meine ich, dass es keine Nutzdaten enthält. Es ist mit dem Hinweis "Segment Lost" versehen. Aber warum ist es leer? Ein "zufälliger" Fehler kann hier wohl ausgeschlossen werden, da dies jedes mal der Fall zu sein scheint. :K
Ein erneutes Senden der Anfrage nach einer abgelaufenen Zeit macht deshalb wohl keinen Sinn.

Freundliche Grüße
Markus
MajorPayne
User
Beiträge: 13
Registriert: Freitag 7. Oktober 2016, 09:56

Zusatz:

Ich habe den Anforderungscode einmal absichtlich falsch geschickt und die letzten beiden hex Stellen abgeschnitten.
Wieder getestet mit dem TCP Tool.

Anfrage:

Bild


Der Server antwortet wie erwartet mit folgendem Code und teilt damit mit, dass der Anforderungscode nicht den Vorgaben entspricht. (Quelle:Handbuch)

Bild

Sende ich eine fehlerhafte Anfrage mit dem Python Programm ist das Telegramm der Antwort ebenfalls leer. Kein Fehlercode - nix.

Kann mir das echt nicht erklären :/

Freundliche Grüße
Markus
MajorPayne
User
Beiträge: 13
Registriert: Freitag 7. Oktober 2016, 09:56

Hallo liebe Forengemeinde!

Ich konnte mit der Hilfe eines Kollegen einen reibungslosen Austausch realisieren.

Hier einmal ein Auszug. Dabei handelt es sich und BlakJack´s Skript. Nur der Sende-Befehl ist ein anderer:

Code: Alles auswählen

	sock.sendall('051500052c000100D310'.decode('hex'))
Hab das Programm zwei mal ausgeführt und dazwischen mit einem Taster dafür gesorgt, dass sich die virtuellen Ausgänge ändern. Hier die Konsolenausgabe:

Bild

Weiß jemand wo da jetzt der Unterschied in den Sendebefehlen liegt?

Freundliche Grüße
Markus
BlackJack

Hm, da fehlt dann wohl ein `connection.flush()` nach dem `write()`-Aufruf bei mir. :oops:
Antworten