Client-Server comm. in PyQt5

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Benutzeravatar
Finux
User
Beiträge: 32
Registriert: Mittwoch 18. September 2019, 13:59

Hallo zusammen,

ich möchte gerne meine clientseitige Logik in eine PyQt5 GUI implementieren. Stoße da aber auf mir nicht so ganz erklärbare Probleme.
Vorab noch eins: Die Kommunikation der client-Logik ist nicht stabil, und auch generell sind einige Sachen äußerst mangelhaft. Mir geht es hier in erster Linie aber um die logische Verknüpfung zu der GUI. OOP-Kenntnisse sind bei mir kaum vorhanden.
Mein Ziel ist es alle Serverantworten in (am liebsten wie in einer Konsolenansicht) in "middleLayout" (output = QLabel --> output.setText) der GUI auszugeben. Ich vermute, dass ich den Code ganz anders strukturieren muss, finde aber keinen vernünftigen Ansatz dafür...
Zudem kommt noch, dass die Kommunikation wenigstens mit dem "msg_send"child-Thread dauerhaft offen bleiben soll (wie kann ich mein command-textfeld via Entertasten-event in mein "send-msg-thread" transportieren? theoretisch würde mir der main-thread für einzelne sendings ja ausreichen und ich kann die Killer-while-Schleife rausschmeißen..)
Vielleicht könnt ihr helfen:

Code: Alles auswählen

import socket, ssl, pprint, sys
import threading
import time
import hashlib
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QPixmap, QFont

IP = '127.0.0.1'
PORT = 4600


class Window(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("CSK Control - YOU NEED TO LOGIN!")
        self.setGeometry(200, 200, 1500, 700)
        self.UI()
        self.show()

       

    def UI(self):
        self.mainDesign()
        self.layout()



    def mainDesign(self):
        ######### left layout widgets #########
        self.u_name_label = QLabel("Username: ")
        self.u_name_input = QLineEdit(self)
        self.u_name_input.setPlaceholderText("auth. user: hell pw:1234")
        self.u_pwd_label = QLabel("Password: ")
        self.u_pwd_input = QLineEdit(self)
        self.u_pwd_input.setEchoMode(QLineEdit.Password)
        self.u_pwd_input.setPlaceholderText("Enter Password")
        self.btn_login = QPushButton("LOGIN", self)
        self.btn_login.clicked.connect(self.connect_to_server)

        ######### middle layout widgets #########
        self.output = QLabel(self)
        self.output.setStyleSheet("background-color: white; font-size: 20pt")
        self.output.setText("TEST")
            ######### middle layout bottom widgets #########
        self.command_label = QLabel(self)
        self.command_label.setText("Command: ")
        self.command_input = QLineEdit(self)
        self.command_input.setPlaceholderText("Enter server command here")

        ######### right layout widgets #########
        self.status = QLabel("STATUS")
        self.status.setStyleSheet("background-color: red; font-size: 16pt")
        #self.u_name_label.setStyleSheet('font-family:Arial Bold')

    def layout(self):
        ######### creating main layout #########
        self.mainLayout = QHBoxLayout()
        self.leftLayout = QFormLayout()
        self.middleLayout = QVBoxLayout()
        self.middleLayout_bottom = QHBoxLayout()
        self.rightLayout = QVBoxLayout()

        ######### adding child layouts #########
        self.mainLayout.addLayout(self.leftLayout, 10)
        self.mainLayout.addLayout(self.middleLayout, 70)
        self.middleLayout.addLayout(self.middleLayout_bottom)
        self.mainLayout.addLayout(self.rightLayout, 20)

        ######### adding widgets #########
            ######### left layout #########
        self.leftLayout.addWidget(self.u_name_label)
        self.leftLayout.addWidget(self.u_name_input)
        self.leftLayout.addWidget(self.u_pwd_label)
        self.leftLayout.addWidget(self.u_pwd_input)
        self.leftLayout.addWidget(self.btn_login)
            ######### middle layout #########
        self.middleLayout.addWidget(self.output)
        self.middleLayout_bottom.addWidget(self.command_label)
        self.middleLayout_bottom.addWidget(self.command_input)
            ######### right layout #########
        self.rightLayout.addWidget(self.status)
        self.rightLayout.addStretch()

        ######### selecting main layout for window #########
        self.setLayout(self.mainLayout)



    def connect_to_server(self):
        context = ssl.SSLContext()
        context.verify_mode = ssl.CERT_REQUIRED
        context.check_hostname = True

        try:
            context.load_verify_locations("/home/fin/server.crt")
            print("***CHECK 1/4- Certificate loading successful")
        except (FileExistsError, FileNotFoundError) as e:
            print(e)
            print("::::: Program will be closed now! :::::")
            sys.exit()

        try:
            # with socket.create_connection((ip, port)) as s:
            conn = context.wrap_socket(socket.socket(socket.AF_INET, socket.SOCK_STREAM), server_hostname="127.0.0.1")
            print("***CHECK 2/4- Socket only supports ssl connection successful")
            try:
                conn.connect((IP, PORT))
                print("***CHECK 3/4- Connection to server successful")
                conn.sendall(b"Thanks for accepting the connection!")
                print("***CHECK 4/4- Bytestring sending successful")
            except:
                print("CONNECTION NOT POSSIBLE! IN 10 SECONDS TRYING TO CONNECT AGAIN..")
                time.sleep(10.0)
                return
        except ssl.CertificateError as e:
            # print("Error {}: {}".format(e.args[0], e.args[1]))
            # print("Error {}:".format(e))  #TODO: Darf Ziel-IP bekannt sein? (Fehlerprovokation bei Hackern) SICHERHEITSMANGEL!
            print("Hostname doesn't match.")
            print("::::: Program will be closed now! :::::")
            sys.exit()
        except ConnectionError as e:
            print(e)
            print("::::: Program will be closed now! :::::")
            sys.exit()

        tell_auth = "username"
        u_name_input = self.u_name_input.text()
        u_pwd_input = self.u_pwd_input.text()

        u_pwd_input = hashlib.sha512(bytes(u_pwd_input, "utf-8"))
        pwd_message = (u_pwd_input.hexdigest())

        conn.sendall(tell_auth.encode("utf-8"))
        conn.sendall(u_name_input.encode("utf-8"))
        conn.sendall(pwd_message.encode("utf-8"))

        msg = conn.recv(4096).decode("utf-8")
        print("\n[{}]: {}".format(IP, msg))
        # self.output.setText("TEST")
        if msg == "Authentication succeeded!":
            # TODO: was passiert nach der succeed message?
            self.setWindowTitle("CSK Control - User: " + self.u_name_input.text())
            self.output.setText(msg)
            t1 = threading.Thread(target=self.msg_receive, args=(conn, IP))
            t1.start()
            t2 = threading.Thread(target=self.msg_print_send, args=(conn, IP))
            t2.start()

            # z = t1.isAlive()
            # print(z)
            # g = t2.isAlive()
            # print(g)
            # c = threading.active_count()
            # print("how many threads are alive: ", c)

            try:
                while 1:
                    # pass
                    time.sleep(1)
            except KeyboardInterrupt as e:
                print(e)
        elif msg == "Authentication failed!":
            self.setWindowTitle("LOGIN FAILED!" + self.u_name_input.text())

    def msg_receive(self, conn, IP):
        try:
            while True:
                i = threading.get_ident()
                print("RECEIVE: ", i)
                msg = conn.recv(4096).decode("utf-8")
                print("\n[{}]: {}".format(IP, msg))
                time.sleep(0.000001)
                if msg == '':
                    print("LOST CONNECTION TO SERVER!")
                    print("TRYING TO RECONNECT... (Refresh Browser!)")  # TODO:
                    conn.close()
                    break
        except OSError as e:
            return

    def msg_print_send(self, conn, IP):
        while True:
            y = threading.get_ident()
            print("SENDING: ", y)
            message = input("\nNachricht: ")
            conn.sendall(message.encode("utf-8"))

            if message == 'exit':
                print("+++++ SOCKET CLOSED +++++")
                conn.close()
                sys.exit()  # TODO: skript beendet sich nicht
                break

def main():
    # -----------------GUI-----------------#
    App = QApplication(sys.argv)
    window = Window()
    sys.exit(App.exec_())
    # -------------------------------------#

if __name__ == '__main__':
    main()

Achso, der aktuelle Stand in meinem Code ist, dass ich die Logindaten von der GUI zum Server schicken kann, die Antwort-accepted-Nachricht erkenne ich auch, aber dann hängt sich die GUI auf...

LG,
Finux
Zuletzt geändert von Finux am Sonntag 27. Oktober 2019, 08:09, insgesamt 1-mal geändert.
Benutzeravatar
Finux
User
Beiträge: 32
Registriert: Mittwoch 18. September 2019, 13:59

Ich glaube, dass die Lösung gar nicht so weit entfernt ist, aber ich sehe einfach den Wald vor lauter Bäumen nicht mehr... :roll:
Benutzeravatar
Finux
User
Beiträge: 32
Registriert: Mittwoch 18. September 2019, 13:59

oh man, bin ich durch, hier natürlich noch die server.py:

Code: Alles auswählen

#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::#
#::::::::::::::::::::::::::::::::::::        MULTITHREAD + SSL       ::::::::::::::::::::::::::::::::::::::::::#
#::::::::::::::::::::::::::::::::::::::::::::: [ server.py ] ::::::::::::::::::::::::::::::::::::::::::::::::::#
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::#
#TODO: logs, try-exp

import socket as socketlib
import ssl
import threading
from time import ctime #formatiertes datetime nutzen!
import logging
import time


HOST = '127.0.0.1'
PORT = 4600

AUTHENTICATIONS = {'fin': 'finja',
                   'haxe': '1337',
                   'hell': 'd404559f602eab6fd602ac7680dacbfaadd13630335e951f097af3900e9de176b6db28512f2e000b9d04fba5133e8b1c6e8df59db3a8ab9d60be4b97cc9e81db'
                   }

logging.basicConfig(filename="log.log", level=logging.DEBUG,
                    format='[%(levelname)s] %(asctime)s - %(name)s :  - LINE_%(lineno)s (%(funcName)s) # PROCESS ID %(process)s >>> THREAD ID %(thread)s\n || %(message)s \n')



def manage_client(connstream, client_socket, addr):
    b = threading.get_ident()
    print("~~ Step 6/6 successful [Server started admitted request in new thread {} with (Client {})] ~~".format(b, addr))
    logging.debug("~~ Step 6/6 successful [Server started admitted request in new thread %s (Client %s)] ~~", b, addr)
    #connstream.sendall(b'Server accepted the connection!')

    usr_accepted = False
    while True:
        data = connstream.recv(4096).decode("utf-8")
        if data == '':
            continue
        else:
            print("Client {}: ".format(addr), data)
            logging.debug("Client %s: %s", addr, data)

            if not usr_accepted:
                if data == 'username':
                    usr_accepted = authentication(connstream, addr)

                    if not usr_accepted:
                        disconnect(connstream, addr)
                        break
                    continue
                else:
                    pass
                    #connstream.sendall(b'Please login first!')
            else:
                if data == 'exit':
                    disconnect(connstream, addr)
                    break
                elif data == "show status":
                    threading.Thread(target=show_status, args=(connstream, addr), daemon=True).start()

                elif data == "count":
                    t_c = threading.Thread(target=count, args=(connstream, addr), daemon=True)
                    t_c.start()
                elif data == 'time':
                    serverLocation_time = ctime()
                    connstream.sendall(serverLocation_time.encode("utf-8"))
                try:
                    # connstream.sendall(b'Servertestmessage')          #DEBUGGING
                    # en = threading.enumerate()
                    # print("how many threads are alive_end: ", en)
                    pass
                except BrokenPipeError as e:
                    print(e)
                    logging.debug(e)
                    logging.exception('Got exception here')
                    print("MESSAGE COULD NOT BE SEND!")
                    logging.debug("MESSAGE COULD NOT BE SEND!")
                    connstream.close()
                    break


def authentication(connstream, addr):
    k = threading.get_ident()
    print("THREAD ID auth: ", k)
    a = threading.enumerate()
    print("how many threads are alive_auth: ", a)
    usr_name = connstream.recv(4096).decode("utf-8")
    print("CLIENT USR_NAME: ", usr_name)
    usr_pwd = connstream.recv(4096).decode("utf-8")
    print("CLIENT USR_PWD: ", usr_pwd)
    if usr_name in AUTHENTICATIONS:
        auth_pwd = AUTHENTICATIONS[usr_name]
        if auth_pwd == usr_pwd:
            print("AUTH YES ACC_1")
            connstream.send(b'Authentication succeeded!')
            print("AUTH YES ACC_2")
            logging.debug("CLIENT AUTHENTICATION FROM {} ACCEPTED".format(addr))
            return True
    print("AUTH NOT ACC_1")
    connstream.send(b'Authentication failed!')
    print("AUTH NOT ACC_2")
    logging.debug("CLIENT AUTHENTICATION FROM {} NOT ACCEPTED".format(addr))
    return False



def disconnect(connstream, addr):
    print("+++++ SOCKET CLOSED +++++   [Client {}]".format(addr))
    logging.debug("+++++ SOCKET CLOSED +++++   [Client {}]".format(addr))
    connstream.close()

def show_status(connstream, addr):
    y = threading.get_ident()
    print("THREAD ID status: ", y)
    s = threading.enumerate()
    print("how many threads are alive_status: ", s)
    server_location_time = ctime()
    connstream.sendall(server_location_time.encode("utf-8"))
    connstream.sendall("Location: CHINA".encode("utf-8"))
    connstream.sendall("Adress: XYZ".encode("utf-8"))
    connstream.sendall("Last update: Oct-11-2019".encode("utf-8"))
    connstream.sendall("Python Version: 3".encode("utf-8"))


def count(connstream, addr):
    o = threading.get_ident()
    print("THREAD ID count: ", o)
    co = threading.enumerate()
    print("how many threads are alive_count: ", co)
    for i in range(1, 10):
        connstream.sendall(str(i).encode("utf-8"))
        print(i)
        time.sleep(3)
    cou = threading.enumerate()
    print("how many threads are alive_countEND: ", cou)


def main():
    try:
        context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
        #context.load_cert_chain(certfile="/home/ispin/CA/server.crt", keyfile="/home/ispin/CA/server.key")
        context.load_cert_chain(certfile="/home/fin/server.crt", keyfile="/home/fin/server.key")
        print("~~ Step 1/6 successful [Loading ssl certification]~~")
        logging.debug("~~ Step 1/6 successful [Loading ssl certification]~~")
    except FileNotFoundError:
        print("CERTIFICATE NOT FOUND!!")
        logging.exception("Certificate could not be loaded. Program is not running anymore. Please restart the program!")
        logging.error("Certificate could not be loaded. Program is not running anymore. Please restart the program!")

    server_socket = socketlib.socket(socketlib.AF_INET, socketlib.SOCK_STREAM)
    with server_socket:
        server_socket.bind((HOST, PORT))
        print("~~ Step 2/6 successful [Socket Binding IP {} on PORT {} as IPv4] ~~".format(HOST, PORT))
        logging.debug("~~ Step 2/6 successful [Socket Binding IP {} on PORT {} as IPv4] ~~".format(HOST, PORT))
        server_socket.listen()
        print("~~ Step 3/6 successful [Server is listening for requests] ~~")
        logging.debug("~~ Step 3/6 successful [Server is listening for requests] ~~")
        try:
            while True:
                    client_socket, addr = server_socket.accept()
                    print("~~ Step 4/6 successful [Server got a request from {}] ~~".format(addr))
                    logging.debug("~~ Step 4/6 successful [Server got a request from %s] ~~", addr)
                    client_socket = context.wrap_socket(client_socket, server_side=True)
                    print("~~ Step 5/6 successful [Request is ssl encrypted now (Client {})] ~~".format(addr))
                    logging.debug("~~ Step 5/6 successful [Request is ssl encrypted now (Client %s)] ~~", addr)

                    threading.Thread(target=manage_client, args=(client_socket, server_socket, addr), daemon=True).start()

        except KeyboardInterrupt as e:
            print(e)
            logging.exception(e)




if __name__ == "__main__":
    main()
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

Du bist schon mit socket-Programmierung überfordert, kennst noch nicht die Grundlagen von Threads und willst jetzt auch noch das dritte riesen Thema angehen, GUI? Und nicht nur das, Du willst auch alles drei miteinander verknüpfen. Komplex hoch drei. Sowas sauber low-level, wie Du es vorhast, zu implementieren würde ich für mich nicht unter 100 Stunden ansetzten. Zum Code sage ich nichts, weil der alles missachtet, was man Dir hier an anderer Stelle schon mal geschrieben hatte. Dazu kommen die typischen Fehler, die man bei GUIs nicht machen darf, wie endlosschleifen, wo es aber auch kein allgemeines Rezept zur Lösung gibt. Programmier Deinen Server mit flask, nimm als Client einen Webbrowser und Du bist mit relativ wenig Kenntnissen schon gut und hast ein solides Programm. Ich würde es so machen, weil ich die Komplexität einer solchen Aufgabe abschätzen kann und diese unter allen Umständen klein wie möglich halten möchte.
__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich werfe noch ungesalzene Passwörter in die Diskussion ein. Und 3rd Party Bibliotheken sind böse(tm) wenn es um Kommunikation geht, aber voll ok bei Qt?!?

Wenn du mit Threads in Qt arbeitest, solltest du auch tunlichst QThread nehmen. Und dich mit den notwendigen Idiomen vertraut machen, das habe ich hier auch schon oft diskutiert. Findet sich aber auch in der Qt Doku. Doch ich würde gar keine Threads benutzen, denn dank Qt kannst du dessen Mainloop benuzten und mit QSocketNotifier arbeiten. Dann muss die gesamte Socket-Kommunikation sauber in eine eigene Klasse gepackt werden, die den Zustandsautomaten deiner Verbindung umsetzt. Nicht Verbunden, anmeldung versandt, Anmeldung fehlgeschlagen, Anmeldung erfolgreich, Verbindung offen, timeouts etc etc etc. und das hängt man dann in die GUI, per Signal Slot Mechanismus.

Ich hab’s schonmal gefragt: was soll das mal werden?
Benutzeravatar
Finux
User
Beiträge: 32
Registriert: Mittwoch 18. September 2019, 13:59

hallo,
danke für eure antworten! ich will euch sicher nicht ärgern, nehmt das bitte, bitte nicht persönlich. stehe unter großem zeitdruck (was als neuling xtrem viel spaß macht..)

nach etwas recherche habe ich versucht die QThreads anzuwenden, habe auch den completten socket-connect-vorgang in eine eigene klasse gepackt. trotz debugging komme ich nicht ganz dahinter wieso meine connect_to_server-funktion nicht angestoßen wird.. was übersehe ich hier?

der spuk der bösen nachfragen und des (für euch augenscheinlichen) ignorierens guter tipps hat bald ein ende. versprochen. dann stehe ich nicht unter diesem zeitdruck etc.

Code: Alles auswählen

import socket, ssl, pprint, sys
#import threading
import time
import hashlib
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QPixmap, QFont
from PyQt5.QtCore import *


IP = '127.0.0.1'
PORT = 4600


class Communication(QThread):

    msg_changed = pyqtSignal(str)

    def connect_to_server(self):
        context = ssl.SSLContext()
        context.verify_mode = ssl.CERT_REQUIRED
        context.check_hostname = True

        try:
            context.load_verify_locations("/home/fin/server.crt")
            print("***CHECK 1/4- Certificate loading successful")
        except (FileExistsError, FileNotFoundError) as e:
            print(e)
            print("::::: Program will be closed now! :::::")
            sys.exit()

        try:
            # with socket.create_connection((ip, port)) as s:
            conn = context.wrap_socket(socket.socket(socket.AF_INET, socket.SOCK_STREAM), server_hostname="127.0.0.1")
            print("***CHECK 2/4- Socket only supports ssl connection successful")
            try:
                conn.connect((IP, PORT))
                print("***CHECK 3/4- Connection to server successful")
                conn.sendall(b"Thanks for accepting the connection!")
                print("***CHECK 4/4- Bytestring sending successful")
            except:
                print("CONNECTION NOT POSSIBLE! IN 10 SECONDS TRYING TO CONNECT AGAIN..")
                time.sleep(10.0)
                return
        except ssl.CertificateError as e:
            # print("Error {}: {}".format(e.args[0], e.args[1]))
            # print("Error {}:".format(e))  #TODO: Darf Ziel-IP bekannt sein? (Fehlerprovokation bei Hackern) SICHERHEITSMANGEL!
            print("Hostname doesn't match.")
            print("::::: Program will be closed now! :::::")
            sys.exit()
        except ConnectionError as e:
            print(e)
            print("::::: Program will be closed now! :::::")
            sys.exit()


    def login(self, conn):
        tell_auth = "username"

        self.connect_to_server()

        u_name_input = self.u_name_input.text()
        u_pwd_input = self.u_pwd_input.text()

        u_pwd_input = hashlib.sha512(bytes(u_pwd_input, "utf-8"))
        pwd_message = (u_pwd_input.hexdigest())

        conn.sendall(tell_auth.encode("utf-8"))
        conn.sendall(u_name_input.encode("utf-8"))
        conn.sendall(pwd_message.encode("utf-8"))

        msg = conn.recv(4096).decode("utf-8")
        print("\n[{}]: {}".format(IP, msg))
        self.msg_changed.emit(msg)
        # self.output.setText("TEST")
        # if msg == "Authentication succeeded!":
        #     # TODO: was passiert nach der succeed message?
        #     t1 = threading.Thread(target=self.msg_receive, args=(conn, IP))
        #     t1.start()
        #     t2 = threading.Thread(target=self.msg_print_send, args=(conn, IP))
        #     t2.start()
        #
        #     try:
        #         while 1:
        #             time.sleep(1)
        #     except KeyboardInterrupt as e:
        #         print(e)
        # elif msg == "Authentication failed!":
        #     self.setWindowTitle("LOGIN FAILED!" + self.u_name_input.text())


    # def msg_receive(self, conn, IP):
    #     try:
    #         while True:
    #             print("RECEIVE: ", i)
    #             msg = conn.recv(4096).decode("utf-8")
    #             print("\n[{}]: {}".format(IP, msg))
    #             time.sleep(0.000001)
    #             if msg == '':
    #                 print("LOST CONNECTION TO SERVER!")
    #                 print("TRYING TO RECONNECT... (Refresh Browser!)")  # TODO:
    #                 conn.close()
    #                 break
    #     except OSError as e:
    #         return

    # def msg_print_send(self, conn, IP):
    #     while True:
    #         print("SENDING: ", y)
    #         message = input("\nNachricht: ")
    #         conn.sendall(message.encode("utf-8"))
    #
    #         if message == 'exit':
    #             print("+++++ SOCKET CLOSED +++++")
    #             conn.close()
    #             sys.exit()  # TODO: skript beendet sich nicht
    #             break




class Window(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("CSK Control - YOU NEED TO LOGIN!")
        self.setGeometry(200, 200, 1500, 700)
        self.UI()
        self.show()


    def UI(self):
        self.mainDesign()
        self.layout()


    def mainDesign(self):
        ######### left layout widgets #########
        self.u_name_label = QLabel("Username: ")
        self.u_name_input = QLineEdit(self)
        self.u_name_input.setPlaceholderText("Enter Username")
        self.u_pwd_label = QLabel("Password: ")
        self.u_pwd_input = QLineEdit(self)
        self.u_pwd_input.setEchoMode(QLineEdit.Password)
        self.u_pwd_input.setPlaceholderText("Enter Password")
        self.btn_login = QPushButton("LOGIN", self)
        self.btn_login.clicked.connect(self.login_btn)

        ######### middle layout widgets #########
        self.output = QLabel(self)
        self.output.setStyleSheet("background-color: white; font-size: 20pt")
        self.output.setText("TEST")
            ######### middle layout bottom widgets #########
        self.command_label = QLabel(self)
        self.command_label.setText("Command: ")
        self.command_input = QLineEdit(self)
        self.command_input.setPlaceholderText("Enter server command here")

        ######### right layout widgets #########
        self.status = QLabel("STATUS")
        self.status.setStyleSheet("background-color: red; font-size: 16pt")
        #self.u_name_label.setStyleSheet('font-family:Arial Bold')

    def login_btn(self):
        self.check_auth = Communication()
        self.check_auth.msg_changed.connect(self.msgChanged)
        self.check_auth.start()

    def msgChanged(self, msg):
        self.setWindowTitle("CSK Control - User: " + self.u_name_input.text())
        self.output.setText(self.msg)


    def layout(self):
        ######### creating main layout #########
        self.mainLayout = QHBoxLayout()
        self.leftLayout = QFormLayout()
        self.middleLayout = QVBoxLayout()
        self.middleLayout_bottom = QHBoxLayout()
        self.rightLayout = QVBoxLayout()

        ######### adding child layouts #########
        self.mainLayout.addLayout(self.leftLayout, 10)
        self.mainLayout.addLayout(self.middleLayout, 70)
        self.middleLayout.addLayout(self.middleLayout_bottom)
        self.mainLayout.addLayout(self.rightLayout, 20)

        ######### adding widgets #########
            ######### left layout #########
        self.leftLayout.addWidget(self.u_name_label)
        self.leftLayout.addWidget(self.u_name_input)
        self.leftLayout.addWidget(self.u_pwd_label)
        self.leftLayout.addWidget(self.u_pwd_input)
        self.leftLayout.addWidget(self.btn_login)
            ######### middle layout #########
        self.middleLayout.addWidget(self.output)
        self.middleLayout_bottom.addWidget(self.command_label)
        self.middleLayout_bottom.addWidget(self.command_input)
            ######### right layout #########
        self.rightLayout.addWidget(self.status)
        self.rightLayout.addStretch()

        ######### selecting main layout for window #########
        self.setLayout(self.mainLayout)


    # def login_action(self):
    #     self.setWindowTitle("CSK Control - User: " + self.u_name_input.text())
    #     self.output.setText(self.msg)




def main():
    # -----------------GUI-----------------#
    App = QApplication(sys.argv)
    window = Window()
    sys.exit(App.exec_())
    # -------------------------------------#

if __name__ == '__main__':
    main()
Benutzeravatar
Finux
User
Beiträge: 32
Registriert: Mittwoch 18. September 2019, 13:59

__deets__ hat geschrieben: Sonntag 27. Oktober 2019, 10:44denn dank Qt kannst du dessen Mainloop benuzten und mit QSocketNotifier arbeiten. Dann muss die gesamte Socket-Kommunikation sauber in eine eigene Klasse gepackt werden, die den Zustandsautomaten deiner Verbindung umsetzt. Nicht Verbunden, anmeldung versandt, Anmeldung fehlgeschlagen, Anmeldung erfolgreich, Verbindung offen, timeouts etc etc etc. und das hängt man dann in die GUI, per Signal Slot Mechanismus.
ich habe mir QSocketNotifier angeschaut und nicht verstanden, daher habe ich auf QThread zurückgegriffen.
__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

Der Thread muss auch gestartet werden. Und du unterliegst der ueblichen Fehleinschaetzung zu denken, weil etwas von Thread geerbt wurde, alles was darin ist "magisch" in einem Thread laeuft. Dem ist nicht so. Die OO-Abstraktion Thread als Objekt vs. Thread als nebenlaeufiger Ausfuehrungsstrang von Code ist nicht ohne Brueche.

Hier ein Beispiel einer kleinen GUI, abgeleitet aus etwas das ich hier mal im Forum dazu gebastelt haben. Daran kannst du dich versuchen.

Code: Alles auswählen

#!/usr/bin/env python

import sys
import time

from PyQt5.QtCore import (
    QObject, pyqtSignal,
    QThread,
)

from PyQt5.QtWidgets import (
    QApplication, QDialog,
    QTreeWidget, QTreeWidgetItem,
    QPushButton, QVBoxLayout
)


class Worker(QObject):

    step = pyqtSignal(str)

    def __init__(self):
        QObject.__init__(self)

    def start_work(self):
        self.step.emit("A")
        time.sleep(1)
        self.step.emit("B")
        time.sleep(1)
        self.step.emit("C")


class MainThread(QDialog):

    def __init__(self, parent=None):
        QDialog.__init__(self, parent)
        # Thread der im Hintergrund sitzt
        # und einen eigenen Mainloop hat
        self.task_thread = QThread()
        self.task_thread.start()

        # Worker dessen slot "start_work"
        # durch das bewegen in den worker-thread
        # auch von dem ausgefuehrt werden.
        worker = self.task_thread.work = Worker()
        worker.moveToThread(self.task_thread)
        # ACHTUNG: signal/slots connections zum Worker duerfen
        # ERST nach Verschiebung in den Hintergrundthread passiern.
        # Dadurch wird add_item im MAINTHREAD aufgerufen (wichtig, weil
        # es etwas an der GUI dreht
        worker.step.connect(self.add_item)

        self.setWindowTitle('ThreadTest')

        layout = QVBoxLayout(self)

        self.tree = QTreeWidget(self)

        self.create_worker_thread_button = QPushButton(self)
        self.create_worker_thread_button.setText(
            "Start work"
        )
        # WICHTIG: das hier ist der Moment, in dem das Signal
        # des Buttons an den Slot des Workers gebunden wird. Wenn
        # dann der Button gedrueckt wird, beginnt im Hintergrund Arbeit
        self.create_worker_thread_button.clicked.connect(
            worker.start_work
        )

        self.close_button = QPushButton(self)
        self.close_button.setText("Close")
        self.close_button.clicked.connect(self.close)

        layout.addWidget(self.tree)
        layout.addWidget(self.create_worker_thread_button)
        layout.addWidget(self.close_button)

    def add_item(self, text):
        parent = QTreeWidgetItem(self.tree)
        self.tree.addTopLevelItem(parent)
        parent.setText(0, text)


def main():
    app = QApplication(sys.argv)

    w = MainThread()
    w.show()

    app.exec_()
    sys.exit()


if __name__ == '__main__':
    main()
__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

Und hier ein Beispiel mit Server, Connections und QSocketNotifier. Das halte ich fuer deutlich vielversprechender.

Code: Alles auswählen

#!/usr/bin/env python

import sys
import time
from functools import partial

from PyQt5.QtCore import (
    QObject, pyqtSignal,
    QSocketNotifier
)

import socket

from PyQt5.QtWidgets import (
    QApplication, QDialog,
    QTreeWidget, QTreeWidgetItem,
    QPushButton, QVBoxLayout
)


HOST = ""
PORT = 10000

def debug_trace():
  '''Set a tracepoint in the Python debugger that works with Qt'''
  from PyQt5.QtCore import pyqtRemoveInputHook

  # Or for Qt5
  #from PyQt5.QtCore import pyqtRemoveInputHook

  from pdb import set_trace
  pyqtRemoveInputHook()
  set_trace()


class Connection(QObject):

    state = pyqtSignal(str)

    def __init__(self, socket, addr):
        super().__init__(parent=None)
        self._socket = socket
        self.addr = addr
        notifier = QSocketNotifier(
            self._socket.fileno(), QSocketNotifier.Read, self
        )
        notifier.activated.connect(self._data_incoming)
        self._buffer = b""

    def _data_incoming(self, _):
        data = self._socket.recv(1) # Bewusst klein, um zu zeigen das eine Nachricht in Teilen kommen kann. Sollte groesser sein.
        if data:
            self._buffer += data
            print(self._buffer)
        else:
            # no data means we are closed!
            self._socket.close()
            self.state.emit("closed")


class Server(QObject):

    client_connected = pyqtSignal(object)

    def __init__(self):
        super().__init__(parent=None)
        self._connections = []
        self._server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self._server_socket.bind((HOST, PORT))
        notifier = QSocketNotifier(self._server_socket.fileno(), QSocketNotifier.Read, self)
        notifier.activated.connect(self._server_connection_opened)
        self._server_socket.listen()

    def _server_connection_opened(self, *args):
        # wir haben einen client der anklopft. Den muessen
        # wir akzeptieren
        client_socket, addr = self._server_socket.accept()
        connection = Connection(client_socket, addr)
        self._connections.append(connection)
        self.client_connected.emit(connection)


class MainThread(QDialog):

    def __init__(self, server, parent=None):
        QDialog.__init__(self, parent)
        self.setWindowTitle('ThreadTest')
        self._server = server
        server.client_connected.connect(self.add_connection)

        layout = QVBoxLayout(self)

        self.tree = QTreeWidget(self)

        self.close_button = QPushButton(self)
        self.close_button.setText("Close")
        self.close_button.clicked.connect(self.close)

        layout.addWidget(self.tree)
        layout.addWidget(self.close_button)

    def add_connection(self, connection):
        item = QTreeWidgetItem(self.tree)
        self.tree.addTopLevelItem(item)
        item.setText(0, "Client {}".format(str(connection.addr)))
        connection.state.connect(
            partial(lambda connection, item, state: item.setText(0, "{}: {}".format(connection.addr, state)),
                connection, item
            )
        )


def main():
    app = QApplication(sys.argv)

    server = Server()
    w = MainThread(server)
    w.show()

    app.exec_()
    sys.exit()


if __name__ == '__main__':
    main()
Benutzeravatar
Finux
User
Beiträge: 32
Registriert: Mittwoch 18. September 2019, 13:59

__deets__ hat geschrieben: Sonntag 27. Oktober 2019, 18:01Der Thread muss auch gestartet werden.

mit

Code: Alles auswählen

    def login_btn(self):
        self.check_auth = Communication()
        self.check_auth.msg_changed.connect(self.msgChanged)
        self.check_auth.start()
starte ich ihn doch, oder? :?:


__deets__ hat geschrieben: Sonntag 27. Oktober 2019, 18:01Und du unterliegst der ueblichen Fehleinschaetzung zu denken, weil etwas von Thread geerbt wurde, alles was darin ist "magisch" in einem Thread laeuft. Dem ist nicht so.
kannst du mir das an meinem code benennen? so ganz kann ich dir da nicht folgen...


__deets__ hat geschrieben: Sonntag 27. Oktober 2019, 18:01Die OO-Abstraktion Thread als Objekt vs. Thread als nebenlaeufiger Ausfuehrungsstrang von Code ist nicht ohne Brueche.
auch hier, sry ich verstehe es nicht ganz was du damit meinst...

Ich versuche gerade dein Code-Bsp. zu verstehen, brauche aber nen moment um reinzukommen. vielen dank!
Benutzeravatar
Finux
User
Beiträge: 32
Registriert: Mittwoch 18. September 2019, 13:59

__deets__ hat geschrieben: Sonntag 27. Oktober 2019, 18:37 Und hier ein Beispiel mit Server, Connections und QSocketNotifier. Das halte ich fuer deutlich vielversprechender.

server-seitig bin ich (thank god!) nicht auf eine gui angewiesen :) dennoch danke!
__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das Beispiel fuer den Server ist genauso gut auch fuer den Client. Dann gibt's halt keinen Server, sondern direkt eine Connection.

Und was das Threading angeht - ja, du erzeugst einen Thread. Du startest den auch. Aber der macht dann nichts. Wie in meinem Beispiel angemerkt - der laesst dann einfach seinen eigenen Event-Loop laufen. login aber zB wird nicht aufgerufen dadurch. Wieso auch. Folgst du jedoch meinem Beispiel, dann kannst du ein signal an den Worker schicken (der bei dir eben Communication ist), und wenn das mit einem Slot auf Communication verbunden ist (und dadurch zB auch Parameter bekommen kann!), dann wird *das* im Hintergrund ausgefuehrt.

Und jetzt bin ich weg - Pizza ruft.
Benutzeravatar
Finux
User
Beiträge: 32
Registriert: Mittwoch 18. September 2019, 13:59

so, code umgebaut: nach wie vor kein auslösen von funktion connect_to_server bzw login

was hab ich hier übersehen?

Code: Alles auswählen

import socket, ssl, pprint, sys
#import threading
import time
import hashlib
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QPixmap, QFont
from PyQt5.QtCore import *


IP = '127.0.0.1'
PORT = 4600


class Communication(QObject):

    msg_changed = pyqtSignal(str)

    def __init__(self):
        QObject.__init__(self)

    def connect_to_server(self):
        context = ssl.SSLContext()
        context.verify_mode = ssl.CERT_REQUIRED
        context.check_hostname = True

        try:
            context.load_verify_locations("/home/fin/server.crt")
            print("***CHECK 1/4- Certificate loading successful")
        except (FileExistsError, FileNotFoundError) as e:
            print(e)
            print("::::: Program will be closed now! :::::")
            sys.exit()

        try:
            # with socket.create_connection((ip, port)) as s:
            conn = context.wrap_socket(socket.socket(socket.AF_INET, socket.SOCK_STREAM), server_hostname="127.0.0.1")
            print("***CHECK 2/4- Socket only supports ssl connection successful")
            try:
                conn.connect((IP, PORT))
                print("***CHECK 3/4- Connection to server successful")
                conn.sendall(b"Thanks for accepting the connection!")
                print("***CHECK 4/4- Bytestring sending successful")
            except:
                print("CONNECTION NOT POSSIBLE! IN 10 SECONDS TRYING TO CONNECT AGAIN..")
                time.sleep(10.0)
                return
        except ssl.CertificateError as e:
            # print("Error {}: {}".format(e.args[0], e.args[1]))
            # print("Error {}:".format(e))  #TODO: Darf Ziel-IP bekannt sein? (Fehlerprovokation bei Hackern) SICHERHEITSMANGEL!
            print("Hostname doesn't match.")
            print("::::: Program will be closed now! :::::")
            sys.exit()
        except ConnectionError as e:
            print(e)
            print("::::: Program will be closed now! :::::")
            sys.exit()


    def login(self, conn):
        tell_auth = "username"

        self.connect_to_server()

        u_name_input = self.u_name_input.text()
        u_pwd_input = self.u_pwd_input.text()

        u_pwd_input = hashlib.sha512(bytes(u_pwd_input, "utf-8"))
        pwd_message = (u_pwd_input.hexdigest())

        conn.sendall(tell_auth.encode("utf-8"))
        conn.sendall(u_name_input.encode("utf-8"))
        conn.sendall(pwd_message.encode("utf-8"))

        msg = conn.recv(4096).decode("utf-8")
        print("\n[{}]: {}".format(IP, msg))
        self.msg_changed.emit(msg)
        # self.output.setText("TEST")
        # if msg == "Authentication succeeded!":
        #     # TODO: was passiert nach der succeed message?
        #     t1 = threading.Thread(target=self.msg_receive, args=(conn, IP))
        #     t1.start()
        #     t2 = threading.Thread(target=self.msg_print_send, args=(conn, IP))
        #     t2.start()
        #
        #     try:
        #         while 1:
        #             time.sleep(1)
        #     except KeyboardInterrupt as e:
        #         print(e)
        # elif msg == "Authentication failed!":
        #     self.setWindowTitle("LOGIN FAILED!" + self.u_name_input.text())


    # def msg_receive(self, conn, IP):
    #     try:
    #         while True:
    #             print("RECEIVE: ", i)
    #             msg = conn.recv(4096).decode("utf-8")
    #             print("\n[{}]: {}".format(IP, msg))
    #             time.sleep(0.000001)
    #             if msg == '':
    #                 print("LOST CONNECTION TO SERVER!")
    #                 print("TRYING TO RECONNECT... (Refresh Browser!)")  # TODO:
    #                 conn.close()
    #                 break
    #     except OSError as e:
    #         return

    # def msg_print_send(self, conn, IP):
    #     while True:
    #         print("SENDING: ", y)
    #         message = input("\nNachricht: ")
    #         conn.sendall(message.encode("utf-8"))
    #
    #         if message == 'exit':
    #             print("+++++ SOCKET CLOSED +++++")
    #             conn.close()
    #             sys.exit()  # TODO: skript beendet sich nicht
    #             break




class Window(QWidget):
    # def __init__(self):
    #     super().__init__()

    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.setWindowTitle("CSK Control - YOU NEED TO LOGIN!")
        self.setGeometry(200, 200, 1500, 700)
        self.UI()
        self.show()


    def UI(self):
        self.mainDesign()
        self.layout()


    def mainDesign(self):
        ######### left layout widgets #########
        self.u_name_label = QLabel("Username: ")
        self.u_name_input = QLineEdit(self)
        self.u_name_input.setPlaceholderText("Enter Username")
        self.u_pwd_label = QLabel("Password: ")
        self.u_pwd_input = QLineEdit(self)
        self.u_pwd_input.setEchoMode(QLineEdit.Password)
        self.u_pwd_input.setPlaceholderText("Enter Password")
        self.btn_login = QPushButton("LOGIN", self)
        self.btn_login.clicked.connect(self.login_btn)

        ######### middle layout widgets #########
        self.output = QTreeWidget(self)
        #self.output.setStyleSheet("background-color: white; font-size: 20pt")
        #self.output.setText("TEST")
            ######### middle layout bottom widgets #########
        self.command_label = QLabel(self)
        self.command_label.setText("Command: ")
        self.command_input = QLineEdit(self)
        self.command_input.setPlaceholderText("Enter server command here")

        ######### right layout widgets #########
        self.status = QLabel("STATUS")
        self.status.setStyleSheet("background-color: red; font-size: 16pt")
        #self.u_name_label.setStyleSheet('font-family:Arial Bold')

    def login_btn(self):
        self.check_auth = QThread()
        self.check_auth.start()
        #self.check_auth = QThread()
        auth_checker = self.check_auth.work = Communication()
        auth_checker.moveToThread(self.check_auth)
        auth_checker.msg_changed.connect(self.msgChanged)

        # self.btn_login.clicked.connect(auth_checker.login)
        # self.check_auth.msg_changed.connect(self.msgChanged)
        # self.check_auth.start()

    def msgChanged(self, messg):
        self.setWindowTitle("CSK Control - User: " + self.u_name_input.text())
        parent = QTreeWidgetItem(self.output)
        self.output.addTopLevelItem(parent)
        parent.setText(0, messg)

        #self.output.setText(self.messg)


    def layout(self):
        ######### creating main layout #########
        self.mainLayout = QHBoxLayout()
        self.leftLayout = QFormLayout()
        self.middleLayout = QVBoxLayout()
        self.middleLayout_bottom = QHBoxLayout()
        self.rightLayout = QVBoxLayout()

        ######### adding child layouts #########
        self.mainLayout.addLayout(self.leftLayout, 10)
        self.mainLayout.addLayout(self.middleLayout, 70)
        self.middleLayout.addLayout(self.middleLayout_bottom)
        self.mainLayout.addLayout(self.rightLayout, 20)

        ######### adding widgets #########
            ######### left layout #########
        self.leftLayout.addWidget(self.u_name_label)
        self.leftLayout.addWidget(self.u_name_input)
        self.leftLayout.addWidget(self.u_pwd_label)
        self.leftLayout.addWidget(self.u_pwd_input)
        self.leftLayout.addWidget(self.btn_login)
            ######### middle layout #########
        self.middleLayout.addWidget(self.output)
        self.middleLayout_bottom.addWidget(self.command_label)
        self.middleLayout_bottom.addWidget(self.command_input)
            ######### right layout #########
        self.rightLayout.addWidget(self.status)
        self.rightLayout.addStretch()

        ######### selecting main layout for window #########
        self.setLayout(self.mainLayout)


    # def login_action(self):
    #     self.setWindowTitle("CSK Control - User: " + self.u_name_input.text())
    #     self.output.setText(self.msg)




def main():
    # -----------------GUI-----------------#
    App = QApplication(sys.argv)
    window = Window()
    sys.exit(App.exec_())
    # -------------------------------------#

if __name__ == '__main__':
    main()
__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich sehe nirgendwo eine Verbindung eines Signals der GUI mit einem Slot des Workers. Geschweige denn, dass das Signal ausgelöst wird. Also wird da auch nichts aufgerufen. Schau nochmal genau auf mein Beispiel, wo die Arbeit stattfindet, und wie das ausgelöst wird.
Benutzeravatar
Finux
User
Beiträge: 32
Registriert: Mittwoch 18. September 2019, 13:59

ich könnte schwören ich habe die verknüpfungen genauso übernommen wie sie bei dir im code war.
ich versuch mal meinen gedanken des weges zu gehen wenn der loginbutton seinen klick erhält:
self.btn_login = QPushButton("LOGIN", self)
self.btn_login.clicked.connect(self.login_btn)
Anlegen des Buttons, Klickauslöser und dem Aufruf der Funktion login_btn

Code: Alles auswählen

        auth_checker = self.check_auth.work = Communication()
        auth_checker.moveToThread(self.check_auth)
        auth_checker.msg_changed.connect(self.msgChanged)
Von der Funktion login_btn wird mein auth_checker geschaffen, der in der msgChanged..

Code: Alles auswählen

        msg = conn.recv(4096).decode("utf-8")
        print("\n[{}]: {}".format(IP, msg))
        self.msg_changed.emit(msg)
...seinen emit aus der def login der Klasse Communication erhält.

Das ist meine "Märchenidee" gewesen...
Benutzeravatar
Finux
User
Beiträge: 32
Registriert: Mittwoch 18. September 2019, 13:59

wenn ich mit dem debugger durchgehe schmiert mir das window schon mit dem aufruf via show() ab
__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das ist aber die andere Richtung. Das abliefern der Ergebnisse. Es muss aber ein Slot von Communication getriggert werden. Wenn das zb Login sein soll, dass ja auch noch ein Argument will, brauchst du ein neues Signal in deiner GUI klasse, mit einem str Argument. Das connected zu dem login. Und dann emittest du das
Benutzeravatar
Finux
User
Beiträge: 32
Registriert: Mittwoch 18. September 2019, 13:59

vielen, vielen dank!

soweit bin ich successful, was mich jetzt aber noch wurmt ist die threading-geschichte:

ich möchte also in der lage sein via command_input etwas senden zu können. tue ich dies außerhalb meiner login-funktion, werde ich vom server als neuer client betrachtet, was natürlich allen zweck des login und der authentification verwirft. d.h. ich brauche (wenn das überhaupt klappen sollte..) den inhalt meiner conn - variable der Connection-Klasse und "fuddel" damit in der Window-Klasse rum, oder ich lasse conn brav in der Connection-Klasse, müsste dann aber dort einen Thread erstellen, damit ich (wie zu meinem stand vor der GUI) in der lage bin gleichzeitig receiven und senden zu können. ich würde hier ungern einen thread blockieren müssen, nur um befehle zu senden....

Code: Alles auswählen

import socket, ssl, pprint, sys
#import threading
import time
import hashlib
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QPixmap, QFont
from PyQt5.QtCore import *


IP = '127.0.0.1'
PORT = 4600


class Communication(QObject):

    msg_changed = pyqtSignal(str)
    conn_var = pyqtSignal(ssl.SSLSocket) #TODO: ??? <class 'ssl.SSLSocket'>

    def __init__(self, u_name_input, u_pwd_input):
        QObject.__init__(self)
        self.u_name_input = u_name_input
        self.u_pwd_input = u_pwd_input

    def connect_to_server(self):
        context = ssl.SSLContext()
        context.verify_mode = ssl.CERT_REQUIRED
        context.check_hostname = True

        try:
            context.load_verify_locations("/home/fin/server.crt")
            print("***CHECK 1/4- Certificate loading successful")
        except (FileExistsError, FileNotFoundError) as e:
            print(e)
            print("::::: Program will be closed now! :::::")
            sys.exit()

        try:
            # with socket.create_connection((ip, port)) as s:
            self.conn = context.wrap_socket(socket.socket(socket.AF_INET, socket.SOCK_STREAM), server_hostname="127.0.0.1")
            print("***CHECK 2/4- Socket only supports ssl connection successful")
            try:
                self.conn.connect((IP, PORT))
                print("***CHECK 3/4- Connection to server successful")                
                print(type(self.conn))
                self.conn.sendall(b"Thanks for accepting the connection!")
                print("***CHECK 4/4- Bytestring sending successful")
            except:
                print("CONNECTION NOT POSSIBLE! IN 10 SECONDS TRYING TO CONNECT AGAIN..")
                time.sleep(10.0)
                return
        except ssl.CertificateError as e:
            # print("Error {}: {}".format(e.args[0], e.args[1]))
            # print("Error {}:".format(e))  #TODO: Darf Ziel-IP bekannt sein? (Fehlerprovokation bei Hackern) SICHERHEITSMANGEL!
            print("Hostname doesn't match.")
            print("::::: Program will be closed now! :::::")
            sys.exit()
        except ConnectionError as e:
            print(e)
            print("::::: Program will be closed now! :::::")
            sys.exit()


    def login(self):
        tell_auth = "username"

        self.connect_to_server()

        u_name_input = self.u_name_input.text()
        print(u_name_input)
        u_pwd_input = self.u_pwd_input.text()

        u_pwd_input = hashlib.sha512(bytes(u_pwd_input, "utf-8"))
        pwd_message = (u_pwd_input.hexdigest())

        self.conn.sendall(tell_auth.encode("utf-8"))
        self.conn.sendall(u_name_input.encode("utf-8"))
        self.conn.sendall(pwd_message.encode("utf-8"))

        try:
            while True:
                msg = self.conn.recv(4096).decode("utf-8")
                print("\n[{}]: {}".format(IP, msg))
                self.msg_changed.emit(msg)
                time.sleep(0.000001)
                if (msg == '') or (msg == "Authentication failed!"):
                    self.msg_changed.emit("LOST CONNECTION TO SERVER!")
                    self.msg_changed.emit("Please Login again!")
                    self.conn.close()
                    break

        except OSError as e:
            self.msg_changed.emit("Connection not possible. Please restart the program!")
            return
        # self.output.setText("TEST")
        # if msg == "Authentication succeeded!":
        #     # TODO: was passiert nach der succeed message?
        #     t1 = threading.Thread(target=self.msg_receive, args=(conn, IP))
        #     t1.start()
        #     t2 = threading.Thread(target=self.msg_print_send, args=(conn, IP))
        #     t2.start()
        #
        #     try:
        #         while 1:
        #             time.sleep(1)
        #     except KeyboardInterrupt as e:
        #         print(e)
        # elif msg == "Authentication failed!":
        #     self.setWindowTitle("LOGIN FAILED!" + self.u_name_input.text())


    # def msg_receive(self, conn, IP):
    #     try:
    #         while True:
    #             print("RECEIVE: ", i)
    #             msg = conn.recv(4096).decode("utf-8")
    #             print("\n[{}]: {}".format(IP, msg))
    #             time.sleep(0.000001)
    #             if msg == '':
    #                 print("LOST CONNECTION TO SERVER!")
    #                 print("TRYING TO RECONNECT... (Refresh Browser!)")  # TODO:
    #                 conn.close()
    #                 break
    #     except OSError as e:
    #         return

    # def msg_print_send(self, conn, IP):
    #     while True:
    #         print("SENDING: ", y)
    #         message = input("\nNachricht: ")
    #         conn.sendall(message.encode("utf-8"))
    #
    #         if message == 'exit':
    #             print("+++++ SOCKET CLOSED +++++")
    #             conn.close()
    #             sys.exit()  # TODO: skript beendet sich nicht
    #             break




class Window(QWidget):
    # def __init__(self):
    #     super().__init__()

    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.setWindowTitle("CSK Control - YOU NEED TO LOGIN!")
        self.setGeometry(200, 200, 1500, 700)
        self.UI()
        self.show()


    def UI(self):
        self.mainDesign()
        self.layout()


    def mainDesign(self):

        #self.login_btn()

        ######### left layout widgets #########
        self.u_name_label = QLabel("Username: ")
        self.u_name_input = QLineEdit(self)
        self.u_name_input.setPlaceholderText("Enter Username")
        self.u_pwd_label = QLabel("Password: ")
        self.u_pwd_input = QLineEdit(self)
        self.u_pwd_input.setEchoMode(QLineEdit.Password)
        self.u_pwd_input.setPlaceholderText("Enter Password")
        self.btn_login = QPushButton("LOGIN", self)
        # self.btn_login.clicked.connect(self.auth_checker.login_btn)
        # self.btn_login.clicked.connect(self.auth_checker.login)

        ######### middle layout widgets #########
        self.output = QTreeWidget(self)
        #self.output.setStyleSheet("background-color: white; font-size: 20pt")
        #self.output.setText("TEST")
            ######### middle layout bottom widgets #########
        self.command_label = QLabel(self)
        self.command_label.setText("Command: ")
        self.command_input = QLineEdit(self)
        self.command_input.setPlaceholderText("Enter server command here")

        ######### right layout widgets #########
        self.status = QLabel("STATUS")
        self.status.setStyleSheet("background-color: red; font-size: 16pt")
        #self.u_name_label.setStyleSheet('font-family:Arial Bold')

        self.login_btn()

        self.btn_login.clicked.connect(self.auth_checker.login)
        #self.command_input.returnPressed.connect(self.onClick)



    def layout(self):
        ######### creating main layout #########
        self.mainLayout = QHBoxLayout()
        self.leftLayout = QFormLayout()
        self.middleLayout = QVBoxLayout()
        self.middleLayout_bottom = QHBoxLayout()
        self.rightLayout = QVBoxLayout()

        ######### adding child layouts #########
        self.mainLayout.addLayout(self.leftLayout, 10)
        self.mainLayout.addLayout(self.middleLayout, 70)
        self.middleLayout.addLayout(self.middleLayout_bottom)
        self.mainLayout.addLayout(self.rightLayout, 20)

        ######### adding widgets #########
            ######### left layout #########
        self.leftLayout.addWidget(self.u_name_label)
        self.leftLayout.addWidget(self.u_name_input)
        self.leftLayout.addWidget(self.u_pwd_label)
        self.leftLayout.addWidget(self.u_pwd_input)
        self.leftLayout.addWidget(self.btn_login)
            ######### middle layout #########
        self.middleLayout.addWidget(self.output)
        self.middleLayout_bottom.addWidget(self.command_label)
        self.middleLayout_bottom.addWidget(self.command_input)
            ######### right layout ##########
        self.rightLayout.addWidget(self.status)
        self.rightLayout.addStretch()

        ######### selecting main layout for window #########
        self.setLayout(self.mainLayout)


    # def login_action(self):
    #     self.setWindowTitle("CSK Control - User: " + self.u_name_input.text())
    #     self.output.setText(self.msg)


    def login_btn(self):
        self.check_auth = QThread()
        self.check_auth.start()
        #self.check_auth = QThread()
        self.auth_checker = self.check_auth.work = Communication(self.u_name_input, self.u_pwd_input)
        #myLogin = Communication(self.u_name_input, self.u_pwd_input)
        self.auth_checker.moveToThread(self.check_auth)
        self.auth_checker.msg_changed.connect(self.msgChanged)

    def send_command(self):
        pass


    def msgChanged(self, messg):
        if messg == "Authentication failed!":
            self.setWindowTitle("CSK Control - LOGIN FAILED!")
        elif messg == "Authentication succeeded!":
            self.setWindowTitle("CSK Control - User: " + self.u_name_input.text())
            self.status.setStyleSheet("background-color: green; font-size: 16pt")
        parent = QTreeWidgetItem(self.output)
        self.output.addTopLevelItem(parent)
        parent.setText(0, messg)

def main():
    # -----------------GUI-----------------#
    App = QApplication(sys.argv)
    window = Window()
    sys.exit(App.exec_())
    # -------------------------------------#

if __name__ == '__main__':
    main()
Benutzeravatar
sparrow
User
Beiträge: 4193
Registriert: Freitag 17. April 2009, 10:28

Nimm Flask und bau es als Webservice.
Das was du tust ist Arbeitsbeschaffung mit einem fürchterlich schlechten Resultat.
Benutzeravatar
Finux
User
Beiträge: 32
Registriert: Mittwoch 18. September 2019, 13:59

das geht leider aus privaten gründen nicht. ich bin ja mittlerweile auch vom ziel nicht mehr weit entfernt, und klinge es noch für euch so unlogisch: "das fürchterliche ergebnis reicht mir tatsächlich". ich kann es derzeit nur leider nicht erklären und bitte daher um verständnis.
Antworten