From 954d782075c1be474f6593b12c0953e96210419d Mon Sep 17 00:00:00 2001 From: Alexander Schulz <alexander.schulz@student.reutlingen-university.de> Date: Sun, 7 Jan 2024 23:34:00 +0100 Subject: [PATCH] multiple standalone server --- chat_server.py | 34 ++++++++++- client.py | 18 +++--- main_server.py | 1 - server.py | 163 +++++++++++++++++++++++++++++++++---------------- 4 files changed, 154 insertions(+), 62 deletions(-) diff --git a/chat_server.py b/chat_server.py index aecfed2..00b9172 100644 --- a/chat_server.py +++ b/chat_server.py @@ -1,5 +1,33 @@ +from server import Server +import time import socket +import re + +if __name__ == '__main__': + + client_address = "" + server_id = "" + server_port = 0 + server_cache = dict() + clients_cache = dict() + + BROADCAST_PORT = 49154 + + print("im alive") + MSG = bytes("HI MAIN SERVER", 'utf-8') + + broadcast_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + broadcast_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) + broadcast_socket.sendto(MSG, ('<broadcast>', BROADCAST_PORT)) + print("successfully send message") + + message, server = broadcast_socket.recvfrom(1024) + match = re.search(r'\b([A-Za-z])\b$', message.decode('utf-8')) + server_id = match.group(1) + + print('Received message from server: ', message.decode('utf-8')) + + server = Server(client_address, server_id, server_port, server_cache, clients_cache) + time.sleep(20) + -host = socket.gethostname() -server_address =socket.gethostbyname(host) -print(server_address) \ No newline at end of file diff --git a/client.py b/client.py index 2e32291..13a5038 100644 --- a/client.py +++ b/client.py @@ -52,27 +52,31 @@ class Client(multiprocessing.Process): print('Received message from server: ', data.decode('utf-8')) - # search for ip_address & port in message from server - match = re.search(r'\((\d+\.\d+\.\d+\.\d+):(\d+)\)', data.decode('utf-8')) - ip_address = match.group(1) - port = match.group(2) - self.registered_server = [ip_address, port] + # search for server ip_address in message from server + ip_pattern = r'\b(?:\d{1,3}\.){3}\d{1,3}\b' + matches = re.findall(ip_pattern, data.decode('utf-8')) + # 2nd ip address in message from server is server address + self.registered_server_address = matches[1] #self.registered_server = server - print("My server: ", self.registered_server) + print("My server: ", self.registered_server_address) broadcast_socket.close() def send_message(self): + PORT = 50001 + + print("addr",self.registered_server_address) + while True: message = input() if message.lower() == 'exit': break client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - client_socket.connect((self.registered_server[0], int(self.registered_server[1]))) + client_socket.connect((self.registered_server_address, PORT)) client_socket.sendall(bytes(message, 'utf-8')) diff --git a/main_server.py b/main_server.py index 379de3f..3d3a325 100644 --- a/main_server.py +++ b/main_server.py @@ -1,4 +1,3 @@ -import threading from server import Server import time diff --git a/server.py b/server.py index e555e38..b5554fd 100644 --- a/server.py +++ b/server.py @@ -33,81 +33,140 @@ class Server(multiprocessing.Process): def run(self): print(self.server_id+": "+"Up and running") - #print("SERVER", self.server_id) if self.server_id == "MAIN": client_listener_thread = threading.Thread(target=self.listen_for_clients) client_listener_thread.start() - else: - self.send_reply_to_client() + server_listener_thread = threading.Thread(target=self.listen_for_servers) + server_listener_thread.start() + else: cache_update_listener_thread = threading.Thread(target=self.listen_for_cache_update) client_message_listener_thread = threading.Thread(target=self.listen_for_client_messages) cache_update_listener_thread.start() client_message_listener_thread.start() + + # find highest server ID in cache + def get_last_server_id(self): + if self.local_servers_cache: + return ord(max(self.local_servers_cache, key=lambda k: ord(k))) + #return max(self.local_servers_cache) + else: + # ascii value before A + return 64 + + + def listen_for_servers(self): + + BROADCAST_PORT = 49154 + + # Local host information + MY_HOST = socket.gethostname() + MY_IP = socket.gethostbyname(MY_HOST) + + # 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((self.server_address, BROADCAST_PORT)) + print(self.server_id+": "+"Listening to server register broadcast messages") - def send_reply_to_client(self): - message = 'Hi ' + self.client_address[0] + ' this is your chat-group server ' + self.server_id + '. (' + self.server_address + ':' + str(self.server_port) + ')' + while True: + data, addr = listen_socket.recvfrom(1024) + if data: + message = data.decode('utf-8') + last_server_id = self.get_last_server_id() + new_server_id = chr(last_server_id + 1) + #new_server_id = last_server_id + 1 + self.local_servers_cache[new_server_id] = addr + + print(self.server_id+": "+"Received server register broadcast message:", message) + self.register_server(addr, new_server_id) + + update_cache_thread = threading.Thread(target=self.updateCacheList) + if update_cache_thread.is_alive: + update_cache_thread.run() + else: + update_cache_thread.start() + + def register_server(self, addr, server_id): + message = 'Hi ' + addr[0] + ' this is your chat-group ID: ' + str(server_id) server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) server_socket.connect((self.server_address, self.server_port)) - server_socket.sendto(str.encode(message), self.client_address) + server_socket.sendto(str.encode(message), addr) server_socket.close() + def listen_for_clients(self): - if self.server_id == "MAIN": - BROADCAST_PORT = 5970 - - # Local host information - MY_HOST = socket.gethostname() - MY_IP = socket.gethostbyname(MY_HOST) - - # 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((self.server_address, client_broadcast_listener_port)) - - print(self.server_id+": "+"Listening to client register broadcast messages") - - while True: - data, addr = listen_socket.recvfrom(1024) - if data: - message = data.decode('utf-8') - print(self.server_id+": "+"Received client register broadcast message:", message) - splitted = message.split("_") - if (splitted[0] == 'register'): - self.register_client(splitted[1].upper(), addr) - - update_cache_thread = threading.Thread(target=self.updateCacheList) - if update_cache_thread.is_alive: - update_cache_thread.run() - else: - update_cache_thread.start() + + BROADCAST_PORT = 49153 + + # Local host information + MY_HOST = socket.gethostname() + MY_IP = socket.gethostbyname(MY_HOST) + + # 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((self.server_address, BROADCAST_PORT)) + + print(self.server_id+": "+"Listening to client register broadcast messages") + + while True: + data, addr = listen_socket.recvfrom(1024) + if data: + message = data.decode('utf-8') + print(self.server_id+": "+"Received client register broadcast message:", message) + splitted = message.split("_") + if (splitted[0] == 'register'): + #self.register_client(splitted[1].upper(), addr) + self.register_client(splitted[1].upper(), addr) + + update_cache_thread = threading.Thread(target=self.updateCacheList) + if update_cache_thread.is_alive: + update_cache_thread.run() + else: + update_cache_thread.start() - # Register client. Check if group already exists. If true, add client to existing list, otherwise create new server. - def register_client(self, group, addr): + # Register client. Check if chatgroup exists, if yes answer client with chatgroup server IP + def register_client(self, group, client_addr): + if group not in self.local_servers_cache: - print(self.server_id+": "+"Group "+group+" doesn't exist yet. Creating group..") - server_adress = self.create_server(group, addr) - - group_count = self.filter_groups(group) - - self.local_servers_cache[group] = server_adress - self.client_cache_key_offset = group_count + 1 - client_cache_key = group + str(self.client_cache_key_offset) - self.local_clients_cache[client_cache_key] = addr + print(self.server_id+": "+"Group "+group+" doesn't exist.") else: - print(self.server_id+": "+"Group "+group+" already exists") + print(self.server_id+": "+"Group "+group+" exists") + + + server_addr = self.find_groupchat_server_addresse(group) + self.send_reply_to_client(server_addr, client_addr) + client_count = self.filter_clients(group) self.client_cache_key_offset = client_count + 1 client_cache_key = group + str(self.client_cache_key_offset) - self.local_clients_cache[client_cache_key] = addr + self.local_clients_cache[client_cache_key] = client_addr + + def find_groupchat_server_addresse(self, group): + for key in self.local_servers_cache: + if group == str(key): + addr = self.local_servers_cache[key][0] + + return addr + + def send_reply_to_client(self, server_addr, client_addr): + message = 'Hi ' + client_addr[0] + ' this is your groupchat server: ' + server_addr + server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + server_socket.connect((self.server_address, self.server_port)) + server_socket.sendto(str.encode(message), client_addr) + server_socket.close() def filter_groups(self, group): @@ -191,8 +250,10 @@ class Server(multiprocessing.Process): def listen_for_client_messages(self): + PORT = 50001 + server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - server_socket.bind((self.server_address, self.server_port)) + server_socket.bind((self.server_address, PORT)) server_socket.listen() print(self.server_id+": "+"Group-chat server is listening for client messages at port: ", self.server_port) -- GitLab