From 2de4bb79bb9fa3bfa7d2aec48da2061c044cc6eb Mon Sep 17 00:00:00 2001 From: Quoc Dao <quoc.dao@student.reutlingen-university.de> Date: Thu, 25 Jan 2024 20:30:57 +0100 Subject: [PATCH] broadcast -> multicast --- client.py | 27 ++++++++++----------- server.py | 70 +++++++++++++++++++++++++++++++------------------------ 2 files changed, 54 insertions(+), 43 deletions(-) diff --git a/client.py b/client.py index d2952bf..494c508 100644 --- a/client.py +++ b/client.py @@ -2,16 +2,17 @@ import socket import threading from datetime import datetime +MULTICAST_GROUP_IP = '224.1.1.1' + # Broadcast address and port -BROADCAST_IP = "192.168.0.255" -BROADCAST_PORT = 5973 + +CLIENT_MULTICAST_PORT = 5973 # Local host information MY_HOST = socket.gethostname() MY_IP = socket.gethostbyname(MY_HOST) - class Client(): def __init__(self): self.currentLeader = '' @@ -23,23 +24,23 @@ class Client(): 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 - + def MulticastSendAndReceive(self): # 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)) + multicast_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - # Send broadcast message + # Set the time-to-live for messages to 1 so they do not go past the local network segment + multicast_socket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 1) + + # Send message on multicast address + message = 'New client wants to connect: ' + MY_IP + multicast_socket.sendto(str.encode(message), (MULTICAST_GROUP_IP, CLIENT_MULTICAST_PORT)) 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) + reply, addr = multicast_socket.recvfrom(1024) if reply: # decode received data @@ -82,6 +83,6 @@ class Client(): if __name__ == "__main__": client = Client() - thread1 = threading.Thread(target = client.BroadcastSendAndReceive) + thread1 = threading.Thread(target = client.MulticastSendAndReceive) thread1.start() thread1.join() \ No newline at end of file diff --git a/server.py b/server.py index 0894877..e563590 100644 --- a/server.py +++ b/server.py @@ -2,14 +2,15 @@ import socket import threading from datetime import datetime import time +import struct -BROADCAST_IP = "192.168.0.255" +MULTICAST_GROUP_IP = '224.1.1.1' # Listening port Server Discovery -SERVER_BROADCAST_PORT = 5974 +SERVER_MULTICAST_PORT = 5974 # Listening port Client Discovery -CLIENT_BROADCAST_PORT = 5973 +CLIENT_MULTICAST_PORT = 5973 # Local host information MY_HOST = socket.gethostname() @@ -34,22 +35,26 @@ class Server(): print("Group view is:", self.serverList) - #This function enables the server to listen to the server broadcast port and reply the ip address - def BroadcastListenAndReply(self): + #This function enables the server to listen to the server multicast port and reply the ip address + def MulticastListenAndReply(self): # if my IP is not in the server list add it if MY_IP not in self.serverList: self.serverList.append(MY_IP) # create socket bind to server address - broadcast_listen_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - broadcast_listen_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - broadcast_listen_sock.bind((MY_IP, SERVER_BROADCAST_PORT)) + multicast_listen_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + multicast_listen_sock.bind(('', SERVER_MULTICAST_PORT)) + + # tell the os to add the socket to the multicast group + multicast_group = socket.inet_aton(MULTICAST_GROUP_IP) + mreg = struct.pack('4sL', multicast_group, socket.INADDR_ANY) + multicast_listen_sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreg) while True: - data, address = broadcast_listen_sock.recvfrom(1024) + data, address = multicast_listen_sock.recvfrom(1024) if data: newServer_address = data.decode() @@ -62,7 +67,7 @@ class Server(): self.serverList.append(newServer_address) reply_message = MY_IP - broadcast_listen_sock.sendto(str.encode(reply_message), address) + multicast_listen_sock.sendto(str.encode(reply_message), address) self.printwt('Replied my IP to new participant') @@ -73,19 +78,20 @@ class Server(): self.printwt(f'The current leader IP is: {self.leader_IP}') - #this function enables the server to send a broadcast to the server group and receive the answers of existing members - def BroadcastSendAndReceive(self): + #this function enables the server to send a multicast to the server group and receive the answers of existing members + def MulticastSendAndReceive(self): # create socket - broadcast_group = (BROADCAST_IP, SERVER_BROADCAST_PORT) - broadcast_send_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - broadcast_send_sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) - broadcast_send_sock.settimeout(2) + multicast_group = (MULTICAST_GROUP_IP, SERVER_MULTICAST_PORT) + multicast_send_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + # Set a timeout so the socket does not block indefinitely when trying to receive data. + multicast_send_sock.settimeout(2) - # ... + # Set the time-to-live for messages to 1 so they do not go past the local network segment. + multicast_send_sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 1) message = MY_IP - broadcast_send_sock.sendto(message.encode(), broadcast_group) + multicast_send_sock.sendto(message.encode(), multicast_group) self.printwt("Sent my IP to server group") # if my IP is not in the server list add it @@ -106,7 +112,7 @@ class Server(): try: # receive reply data from the other participants - reply, address = broadcast_send_sock.recvfrom(1024) + reply, address = multicast_send_sock.recvfrom(1024) if reply: reply_address = reply.decode() @@ -126,7 +132,7 @@ class Server(): break if num_responses == 1: - broadcast_send_sock.close() + multicast_send_sock.close() self.isLeader = True self.leader_IP = MY_IP # Hier wird die IP-Adresse des Leaders zugewiesen self.printwt(f'I am the only server in the system, so the leader IP is: {self.leader_IP}') @@ -136,19 +142,23 @@ class Server(): self.print_group_view() - # Listen to client broadcast (request) and reply with Server IP + # Listen to client multicast (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) + # Enable reusing addresses listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # Bind socket to address and port - listen_socket.bind((MY_IP, CLIENT_BROADCAST_PORT)) + listen_socket.bind((MY_IP, CLIENT_MULTICAST_PORT)) + + # tell the os to add the socket to the multicast group + multicast_group = socket.inet_aton(MULTICAST_GROUP_IP) + mreg = struct.pack('4sL', multicast_group, socket.INADDR_ANY) + listen_socket.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreg) - # print("Listening to broadcast messages") + # print("Listening to multicast messages") - # Receiving broadcast massage + # Receiving multicast massage while True: data, addr = listen_socket.recvfrom(1024) @@ -169,13 +179,13 @@ class Server(): data = client_socket.recv(1024) if not data: break - self.broadcast(data, client_socket) + self.multicast(data, client_socket) except: self.clients.remove(client_socket) break - def broadcast(self, message, sender_socket): + def multicast(self, message, sender_socket): for client in self.clients: try: if client != sender_socket: @@ -188,10 +198,10 @@ class Server(): if __name__== '__main__': server = Server() - thread2 = threading.Thread(target = server.BroadcastListenAndReply) + thread2 = threading.Thread(target = server.MulticastListenAndReply) thread2.start() - thread3 = threading.Thread(target = server.BroadcastSendAndReceive) + thread3 = threading.Thread(target = server.MulticastSendAndReceive) thread3.start() thread1 = threading.Thread(target = server.ListenForClientAndReply) -- GitLab