diff --git a/client.py b/client.py index a609e05aa36949c224addcf55602bb7131db93e6..d2952bfaf54e5bd15d6871cd474add50c7c1d6f4 100644 --- a/client.py +++ b/client.py @@ -1,30 +1,87 @@ import socket import threading +from datetime import datetime -def receive_messages(): - while True: - try: - # Empfange Nachricht vom Server - data = client_socket.recv(1024) - print(data.decode('utf-8')) - except: - break - -# Client-Konfiguration -host = '127.0.0.1' -port = 5555 - -# Verbinde zum Server -client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -client_socket.connect((host, port)) -print(f'Du bist jetzt im Chat') - - -# Starte einen Thread, um Nachrichten vom Server zu empfangen -receive_thread = threading.Thread(target=receive_messages) -receive_thread.start() - -# Haupt-Thread zum Senden von Nachrichten -while True: - message = input() - client_socket.send(message.encode('utf-8')) +# Broadcast address and port +BROADCAST_IP = "192.168.0.255" +BROADCAST_PORT = 5973 + +# Local host information +MY_HOST = socket.gethostname() +MY_IP = socket.gethostbyname(MY_HOST) + + + +class Client(): + def __init__(self): + self.currentLeader = '' + self.server_socket = None + + # print the current date and time + def printwt(self, msg): + current_date_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + print(f'[{current_date_time}] {msg}') + + # dynamic discoverey: client sends request to server group and gets the IP of server as reply + def BroadcastSendAndReceive(self): + + message = 'New client wants to connect: ' + MY_IP + + # Create a UDP socket + broadcast_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + # Send message on broadcast address + broadcast_socket.sendto(str.encode(message), (BROADCAST_IP, BROADCAST_PORT)) + + # Send broadcast message + + self.printwt("Sent my IP to server group") + + while True: + try: + # receive reply data (server IP) from the other participants + reply, addr = broadcast_socket.recvfrom(1024) + + if reply: + # decode received data + reply_addr = reply.decode() + self.currentLeader = reply_addr + self.printwt(f'Got Leader address: {self.currentLeader}') + + # Connect to the server using TCP + self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.server_socket.connect((self.currentLeader, 5555)) + print("You have entered the chat room") + + # Starte einen Thread, um Nachrichten zu empfangen + receive_thread = threading.Thread(target=self.receive_messages) + receive_thread.start() + + # Haupt-Thread zum Senden von Nachrichten + while True: + message = input() + timestamped_message = f'[{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}] {message}' + self.server_socket.send(timestamped_message.encode('utf-8')) + + except socket.timeout: + pass + + def receive_messages(self): + while True: + try: + data = self.server_socket.recv(1024) + if not data: + break + print(data.decode('utf-8')) + except: + break + + + + +# starting all simultaneously working procedures +if __name__ == "__main__": + client = Client() + + thread1 = threading.Thread(target = client.BroadcastSendAndReceive) + thread1.start() + thread1.join() \ No newline at end of file diff --git a/server.py b/server.py index bf4da5465296ce81cb4b0aa71bd9414c19bbe104..b09e59b3a4e6b095bf77479f87c869606a747365 100644 --- a/server.py +++ b/server.py @@ -1,53 +1,86 @@ import socket import threading +from datetime import datetime -def handle_client(client_socket, client_address): - while True: - try: - # Empfange Nachricht vom Client - data = client_socket.recv(1024) - if not data: - break +# Listening port +BROADCAST_PORT = 5973 + +# Local host information +MY_HOST = socket.gethostname() +MY_IP = socket.gethostbyname(MY_HOST) + +class Server(): + def __init__(self): + self.leader_IP = '' # fix the leader IP + self.clients = [] + + def printwt(self, msg): + current_date_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + print(f'[{current_date_time}] {msg}') + + # Listen to client broadcast (request) and reply with Server IP + def ListenForClientAndReply(self): + # Create a UDP socket + listen_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + # Set the socket to broadcast and enable reusing addresses + listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) + listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + # Bind socket to address and port + listen_socket.bind((MY_IP, BROADCAST_PORT)) - # Sende die empfangene Nachricht an alle anderen Clients - broadcast(data, client_socket, client_address) - except: - break + print("Listening to broadcast messages") - # Client-Socket schließen - client_socket.close() + # Receiving broadcast massage + while True: + data, addr = listen_socket.recvfrom(1024) -def broadcast(message, sender_socket, sender_address): - for client in clients: - try: - # Sende die Nachricht an alle Clients, außer an den Absender - if client != sender_socket: - client.send(f"{sender_address}: {message}".encode('utf-8')) - except: - # Entferne defekte Verbindungen - clients.remove(client) + if data: + self.printwt(data.decode()) -# Server-Konfiguration -host = '127.0.0.1' -port = 5555 + # if Iam the leader, answer the client including my IP + # if MY_IP == self.leader_IP: + if data: + reply_message = MY_IP + listen_socket.sendto(str.encode(reply_message), addr) + self.printwt('Replied my IP to new client') -# Socket erstellen und binden -server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -server_socket.bind((host, port)) -server_socket.listen(5) + def handle_client(self, client_socket, client_address): + self.clients.append(client_socket) -print(f'Server lauscht auf {host}:{port}') + while True: + try: + data = client_socket.recv(1024) + if not data: + break + self.broadcast(data, client_socket) + + except: + self.clients.remove(client_socket) + break + + def broadcast(self, message, sender_socket): + for client in self.clients: + try: + if client != sender_socket: + client.send(message) + except: + self.clients.remove(client) -# Liste für die verbundenen Clients -clients = [] -while True: - # Warten auf eine Verbindung - client_socket, client_address = server_socket.accept() +# starting all simultaneously working procedures +if __name__== '__main__': + server = Server() - # Neuen Thread für jeden verbundenen Client erstellen - client_thread = threading.Thread(target=handle_client, args=(client_socket, client_address)) - client_thread.start() + thread1 = threading.Thread(target = server.ListenForClientAndReply) + thread1.start() + + # Socket erstellen und binden + server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + server_socket.bind((MY_IP, 5555)) + server_socket.listen(5) + + while True: + client_socket, client_address = server_socket.accept() - # Client-Socket zur Liste hinzufügen - clients.append(client_socket) + client_thread = threading.Thread(target=server.handle_client, args=(client_socket, client_address)) + client_thread.start() \ No newline at end of file