Seite 1 von 1

QtNetwork.QTcpServer - Events

Verfasst: Montag 31. Januar 2022, 19:51
von Pf@nne
Nach längerem hin und her habe ich das Qt-Framework gefunden.
Neben der komfortablen Nutzung von UI-Elementen möchte ich auch die Netzwerkunterstützung nutzen.

Der Server inclusive des Clienthandlings laufen soweit:

Code: Alles auswählen

class Client(QtCore.QObject):
    def SetSocket(self, socket):
        self.rx_counter = 0
        self.tx_counter = 0
        self.socket = socket
        self.socket.connected.connect(self.on_connected)
        self.socket.disconnected.connect(self.on_disconnected)
        self.socket.readyRead.connect(self.on_readyRead)
        frm_main.print_memo("Client Connected from {}:{}".format(self.socket.peerAddress().toString(),
                                                                 self.socket.peerPort()))

    def on_connected(self):
        frm_main.print_memo("Client Connected Event")

    def on_disconnected(self):
        frm_main.print_memo("Client Disconnected")

    def on_readyRead(self):
        msg = self.socket.read(2)
        bytes_to_read = int.from_bytes(msg[1], "big")
        msg += self.socket.read(bytes_to_read)   
        data = bytearray(msg)
        if data[0] == 0x68:  #start
            if data[1] == len(data)-2:
                #S-Frame
                if data[2] & 0b00000011 == 0b01:    #01 S-Frame
                    self.handle_sFrame(data)
                #U-Frame
                if data[2] & 0b00000011 == 0b11:    #11 U-Frame
                    self.handle_uFrame(data)
                #I-Frame        
                if data[2] & 0b00000001 == 0b0:     #.0 I-Frame 
                    self.rx_counter += 1
                    self.handle_iFrame(data)
            else:
                frm_main.print_memo("Wrong size of incomming IEC 60870-5-104 Frame")
     
        
class Server(QtCore.QObject):
    def __init__(self, parent=None):
        QtCore.QObject.__init__(self)
        self.TCP_LISTEN_TO_PORT = 2404
        self.server = QtNetwork.QTcpServer()
        self.server.newConnection.connect(self.on_newConnection)
        self.server.serverPort = self.TCP_LISTEN_TO_PORT
        self.ip = QtNetwork.QHostAddress()
        self.ip.setAddress("127.0.0.1")

    def on_newConnection(self):
        while self.server.hasPendingConnections():
            frm_main.print_memo("Incoming Connection...")
            self.client = Client(self)
            self.client.SetSocket(self.server.nextPendingConnection())

    def StartServer(self):
        if self.server.listen(self.ip, self.TCP_LISTEN_TO_PORT):   #QtNetwork.QHostAddress.Any
            frm_main.print_memo(
                "Server is listening on {}:{}".format(self.ip.toString(),
                                                      self.TCP_LISTEN_TO_PORT))
        else:
            frm_main.print_memo("Server couldn't wake up")

Verständnisprobleme habe ich mit diesen functions:

Code: Alles auswählen

        self.socket.connected.connect(self.on_connected)
        self.socket.disconnected.connect(self.on_disconnected)
        self.socket.readyRead.connect(self.on_readyRead)
on_readyRead: läuft wie erwartet.
on_connected: diese function wird bisher gar nicht aufgerufen. Nicht so schlimm, hätte ich aber anders erwartet.
on_disconnected: wir nur aufgerufen wenn der Client endgültig geschlossen wurde.
Hier hätte ich erwartet, dass ein "durchbooten" des Clients erkannt wird.
Das hat zur Folge, dass mein Client offen bleibt und der durchgebootete Client eine neue Verbindung und damit einen weiteren Client startet.

Hat jemand Erfahrung mit dem Qt-Framework und kann mir hier einen Tipp geben?

Gruß
pf@nne

Re: QtNetwork.QTcpServer - Events

Verfasst: Montag 31. Januar 2022, 21:12
von __deets__
Qt bietet - anders als die schon mehrfach erwähnten Middlewares - keinerlei Mehrwert in Bezug auf socket Programmierung. Da muss man das alles genauso vom Hand herstellen.

Re: QtNetwork.QTcpServer - Events

Verfasst: Dienstag 1. Februar 2022, 16:42
von Pf@nne
OK, schade ....
Ich hätte gedacht, dass die vorhandenen Events mir diese Funktionalitäten abnehmen würden.

Re: QtNetwork.QTcpServer - Events

Verfasst: Dienstag 1. Februar 2022, 17:22
von __deets__
Die Events uebersetzen nur die normalen Ereignisse in die Welt von signals und slots. Nicht mehr, nicht weniger. Die ganzen Fehlerzustaende, die man so bekommen kann, muss man dann durch Erfahrung und veraenderte Protokolle herstellen. "broken pipe" (was dann denke ich mal zu disconnected fuehrt) muss man zB durch eine keep-alive Message aktiv herbeifuehren. Etc. pp.

Oder eben etwas benutzen, welches das schon alles fuer einen gemacht hat. Aber da waren wir ja schon.

Re: QtNetwork.QTcpServer - Events

Verfasst: Mittwoch 2. Februar 2022, 14:10
von HBerger
Qt bietet - anders als die schon mehrfach erwähnten Middlewares - keinerlei Mehrwert in Bezug auf socket Programmierung
Das ist IMHO ein bisserl hart formuliert :-)
Funktional gesehen hasst sicher recht, und bei den high level Sprachen auch vielleicht syntaktisch.

Aber, Qt ist initial ein C++ Framework, und die (low level) Socket Schnittstellen sind ein da ein Graus ....
Gibt zwar auch wesentlich bessere Abstraktionen von TCP,
Aber wenn man da Qt eh schon am Hals hat (weil Qt Gui) dann ist QSocket schon auch ne Überlegung wert (wenn man nichts spezielles braucht) .... passt auch besser in die (gesamt) Landschaft.

Wenn man mehr Komfort will, sollte man eh auch über ein anderes / höheres Protokoll nachdenken ... je nach Anwendung, da gibts dann auch ganz andere Bibs dafür.

Re: QtNetwork.QTcpServer - Events

Verfasst: Mittwoch 2. Februar 2022, 14:37
von HBerger
on_disconnected: wir nur aufgerufen wenn der Client endgültig geschlossen wurde.
1. der socket bleibt offen, solange er nicht geschlossen oder zerstört wird, oder die gegenseite halt ...
zerstört wird in python nicht controlliert (garbage collection) also soltest du aktiv close aufrufen, wenn die verbindung schliessen willst.

2. Sockets haben imho kein Fehlerhandling, sprich alles funktioniert über errorcodes bei einer aktiven Aktion.
du muesstest das selber pollen, aka nen read aufrufen, entweder bringt er 0 byte gelesen oder timeout / fehler wenn die verbindung nimmer steht

oder alternativ, wie schon empfohlen, eigenes keep alive implementieren

Re: QtNetwork.QTcpServer - Events

Verfasst: Mittwoch 2. Februar 2022, 20:41
von Pf@nne
OK, danke für die Antworten.
Bei dem von mit genutzten Protokoll sind Testframes ausdrücklich vorgesehen.
Die werde ich dann aktiv triggern und auswerten.