diff --git a/client.py b/client.py index 27db29f..7a6e362 100644 --- a/client.py +++ b/client.py @@ -2,8 +2,7 @@ import socket import threading from random import randint -# Server-Informationen -HOST = '127.0.0.1' +HOST = 'localhost' PORT = 12345 nickname = input("username:") @@ -13,47 +12,38 @@ if nickname == "": print(f"dein username wurde zu {nickname} gesetzt.") run = True + def receive_message(sock): - """ Funktion für das Empfangen von Nachrichten """ - global run while run: try: - # Empfange die Nachricht des Servers msg = sock.recv(1024).decode('utf-8') if not msg: break print(f"\r{msg}\n", end='', flush=True) except: - # Schließe die Verbindung, wenn ein Fehler auftritt - print("Verbindung getrennt.") break def start_client(): - """ Funktion für das Starten des Clients """ global run - # Erstelle den Client-Socket und verbinde ihn mit dem Server client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect((HOST, PORT)) - - # Starte einen Thread für das Empfangen von Nachrichten + threading.Thread(target=receive_message, args=(client,), daemon=True).start() - - client.sendall(nickname.encode('utf-8')) - - while run: - try: + + try: + client.sendall(nickname.encode('utf-8')) + while run: msg = input(">>") if msg.lower() == "exit": - run = False - print("BEENDEN") break client.sendall(msg.encode('utf-8')) - except KeyboardInterrupt: - run = False - print("\rBEENDEN") - break - except: - break + except KeyboardInterrupt: + pass + finally: + run = False + print("BEENDEN") + client.sendall("exit".encode('utf-8')) + client.close() if __name__ == '__main__': start_client() diff --git a/server.py b/server.py index d133c9b..60c059a 100644 --- a/server.py +++ b/server.py @@ -1,69 +1,62 @@ import socket import threading -# Server-Informationen -HOST = '127.0.0.1' +HOST = '0.0.0.0' PORT = 12345 -# Erstelle den Server-Socket server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind((HOST, PORT)) - -# Liste für die Verfolgung der Clients clients = [] +lock = threading.Lock() -def sendanall(conn, msg): - for client in clients: - if client != conn: - try: - client.sendall(msg.encode('utf-8')) - except BrokenPipeError: - print("pipe error") - pass +def send_to_all(conn, msg): + with lock: + for client, _ in clients: + if client != conn: + try: + client.sendall(msg.encode('utf-8')) + except BrokenPipeError: + print("Broken Pipe Error") + pass def handle_client(conn, addr): - """ Funktion für das Behandeln eines einzelnen Clients """ nick = conn.recv(1024).decode('utf-8') print(f"Neuer Client verbunden: {addr} (Nickname: {nick})") - sendanall(conn, f"{nick} hat den Chat betreten") + send_to_all(conn, f"{nick} hat den Chat betreten") + + with lock: + clients.append((conn, nick)) - # Füge den Client zur Liste hinzu - clients.append(conn) - while True: try: - # Empfange die Nachricht des Clients msg = conn.recv(1024).decode('utf-8') if not msg: break elif msg == "exit": print("Client getrennt:", addr) - sendanall(conn, f"{nick} hat den Chat verlassen") - clients.remove(conn) + send_to_all(conn, f"{nick} hat den Chat verlassen") + with lock: + clients.remove((conn, nick)) conn.close() break print(clients) print(f"Nachricht von {addr}: {msg}") - - # Überprüfe, ob das Socket noch geöffnet ist, bevor Sie versuchen zu senden + if conn.fileno() != -1: - sendanall(conn, f"<{nick}>:{msg}") + send_to_all(conn, f"<{nick}>:{msg}") except ConnectionResetError: - # Wenn eine Verbindungsreset-Ausnahme auftritt (Client beendet ohne "exit" zu senden) print("Client getrennt (Verbindungsreset):", addr) - sendanall(conn, f"{nick} hat den Chat verlassen") - clients.remove(conn) + send_to_all(conn, f"{nick} hat den Chat verlassen") + with lock: + clients.remove((conn, nick)) conn.close() break def start_server(): - """ Funktion für das Starten des Servers """ server.listen() print(f'Server läuft auf {HOST}:{PORT}') while True: - # Warte auf eingehende Verbindungen conn, addr = server.accept() - # Starte einen neuen Thread für jeden Client threading.Thread(target=handle_client, args=(conn, addr)).start() if __name__ == '__main__': @@ -71,4 +64,8 @@ if __name__ == '__main__': start_server() except KeyboardInterrupt: print("Server wird heruntergefahren.") + with lock: + for client, nick in clients: + send_to_all(client, f"{nick} hat den Chat verlassen") + client.close() server.close()