import json from multiprocessing.connection import Client import pickle import random import socket import sys from message import * # Can change this after testing done from timers import ClientTimer, setTimer class LockClient(): def __init__(self) -> None: with open("config.json", encoding='utf-8') as f: json_dict = json.loads(f.read()) server_addresses = json_dict["servers"] self.server_addresses = [(server_addresses[i], int(server_addresses[i + 1])) for i in range(0, len(server_addresses), 2)] # create a UDP socket self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.sock.bind(('', 0)) self.client_addr = self.sock.getsockname() print(f"Starting client {self.client_addr}", file=sys.stdout) random.seed(0) # For client timer to know whether to resend message self.req_num = 0 def execute(self): prompt_str = "Enter a command (e.g. lock 1 / unlock 1 / exit): " input_str = input(prompt_str) # Input would be "lock 2" / "unlock 1", etc or "exit" try: while input_str != "exit": lock, val = input_str.split(" ", 2) paxos_req = PaxosRequest(self.client_addr, LockCommand(lock, val, self.req_num)) data = pickle.dumps(paxos_req) server_address = random.choice(self.server_addresses) print(f"Sending command {paxos_req} to {server_address}", file=sys.stdout) self.sock.sendto(data, server_address) setTimer(ClientTimer(paxos_req, self.req_num), ClientTimer.CLIENT_RETRY_MILLIS, self.onClientTimer) # receive data back from the server res = pickle.loads(self.sock.recv(1024)) while res.cmd.req_num != self.req_num: res = pickle.loads(self.sock.recv(1024)) self.req_num += 1 print(f"Received response: {res}", file=sys.stdout) if res.value == True: print("Command successfully ran", file=sys.stdout) else: print("Command failed to run", file=sys.stdout) input_str = input(prompt_str) finally: # Close socket self.sock.close() def onClientTimer(self, client_timer: ClientTimer): # print(f"{client_timer}: Callback", file=sys.stdout) if self.req_num <= client_timer.req_num: server_address = random.choice(self.server_addresses) print(f"Resending command {client_timer.paxos_req} to {server_address}", file=sys.stdout) data = pickle.dumps(client_timer.paxos_req) self.sock.sendto(data, server_address) setTimer(client_timer, ClientTimer.CLIENT_RETRY_MILLIS, self.onClientTimer) if __name__ == "__main__": client = LockClient() client.execute()