-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.py
More file actions
105 lines (85 loc) · 3.31 KB
/
server.py
File metadata and controls
105 lines (85 loc) · 3.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import socket
import threading
import sys
def assign_ranks(client, clients, clients_data):
"""assign ranks to clients on first come first serve basis """
clients.append(client)
rank = len(clients) - 1
client.send("Your rank is {}".format(rank).encode())
clients_data[client] = rank
return rank
def distribute_command(clients_data, client_rank, command):
for socket, rank in clients_data.items():
# check if the rank of the recipient client is higher than the rank of the sender
if client_rank < int(rank):
try:
# send the command to the recipient client
new_command = "{} {}".format(command, client_rank)
socket.sendall(new_command.encode())
print(f"Command executed by client with rank {rank}")
return
except Exception as e:
print(f"Error sending command to client with rank {rank}: {e}")
print("[command rejected]...no client with higher rank found to execute command")
def update_after_disconnect(clients):
new_dict = {}
for idx, sock in enumerate(clients):
new_dict[sock] = idx
return new_dict
def handle_client(conn, clients_data, clients):
global current_clients
connected = True
while connected:
message = conn.recv(1024).decode()
if not message:
break
sender_rank = int(message.split()[1])
# if message is a command distribute it
if message.startswith("C"):
command = message[1:]
distribute_command(clients_data, sender_rank, command)
print("[Disconnect] socket {} has disconnected".format(conn.getpeername()))
conn.close()
current_clients -= 1
clients.remove(conn)
del clients_data[conn]
print("[New ranking]")
clients_data = update_after_disconnect(clients)
if len(clients) >= 1:
for sock, rank in clients_data.items():
print("socket {} has rank number {}".format(sock.getpeername(), rank))
for i, c in enumerate(clients):
c.send(f'RYour rank is now {i}'.encode())
else:
print("0 connections")
def start():
global current_clients
clients = []
clients_data = {}
try:
max_clients = int(sys.argv[1])
except IndexError:
max_clients = 5
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('localhost', 5555))
print("[STARTING] Listening for {} clients...".format(max_clients))
server.listen(max_clients)
try:
while True:
if current_clients >= max_clients:
continue
conn, addr = server.accept()
current_clients += 1
print("Accepted client {}".format(addr))
rank = assign_ranks(conn, clients, clients_data)
client_thread = threading.Thread(target=handle_client, args=(conn, clients_data, clients))
client_thread.start()
for sock, rank in clients_data.items():
print("socket {} has rank number {}".format(sock.getpeername(), rank))
except (KeyboardInterrupt, ConnectionResetError):
print('Closing server...')
finally:
# Close the socket and unbind the port
server.close()
current_clients = 0
start()