-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.py
112 lines (99 loc) · 4.33 KB
/
server.py
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
106
107
108
109
110
111
112
import socket
import threading
from encryption import Encrypt
# These are variables used to configure the server.
HEADER = 64
PORT = 5050
SERVER = socket.gethostbyname(socket.gethostname())
ADDR = (SERVER, PORT)
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = "!DISCONNECT"
class Server:
def __init__(self):
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.bind(ADDR)
self.aliases = []
self.clients = []
self.clients_public_keys = []
def broadcast(self, msg, client):
"""
This function broadcasts a message to a specific client.
:param msg: The message that is being sent to the client(s) in the broadcast
:param client: The "client" parameter in this code refers to the specific client that the message is
being sent to. It is likely an object or identifier that represents the connection between the
server and the client
"""
self.send(msg, client)
def handle_client(self, conn, addr):
"""
This function handles a client connection, sends and receives messages, and broadcasts messages
to other clients.
:param conn: conn is a socket object representing the connection between the server and the
client. It is used to send and receive data between the two endpoints
:param addr: The address of the client that has connected to the server. It is a tuple
containing the IP address and the port number of the client
"""
print(f"[NEW CONNECTION] {addr} connected.")
print(f"[SENDING] PUBLIC KEY.")
connected = True
while connected:
msg_length = conn.recv(HEADER).decode(FORMAT)
if msg_length:
msg_length = int(msg_length)
msg = conn.recv(msg_length).decode(FORMAT)
if msg == DISCONNECT_MESSAGE:
connected = False
print(f"[{addr}] {msg}")
else:
print(f"[{addr}] {msg}")
if len(self.clients_public_keys) != 0:
self.send("PUBLIC_KEY", conn)
self.send(self.clients_public_keys[0], conn)
self.send("PUBLIC_KEY", self.clients[0])
self.send(msg, self.clients[0])
else:
print("xxxxxx N0 sending public key")
self.send("NO_PUBLIC_KEY", conn)
self.clients_public_keys.append(msg)
connected = True
while connected:
msg_length = conn.recv(HEADER).decode(FORMAT)
if msg_length:
msg_length = int(msg_length)
msg = conn.recv(msg_length).decode(FORMAT)
print(f"[{addr}] {msg}")
self.broadcast(msg, self.clients[1 - self.clients.index(conn)])
conn.close()
def start(self):
"""
This function starts a server that listens for incoming connections and creates a new thread to
handle each client connection.
"""
self.server.listen()
print(f"[LISTENING] Server is listening on {SERVER}")
while True:
conn, addr = self.server.accept()
self.clients.append(conn)
thread = threading.Thread(
target=self.handle_client, args=(conn, addr))
thread.start()
print(f"[ACTIVE CONNECTIONS] {threading.activeCount() - 1}")
def send(self, msg, client):
"""
This function sends a message to a client by encoding the message, determining its length, and
sending it along with the length to the client.
:param msg: The message to be sent to the client. It should be a string
:param client: The "client" parameter is a socket object representing the client connection that the
message will be sent to
"""
message = msg.encode(FORMAT)
msg_length = len(message)
send_length = str(msg_length).encode(FORMAT)
send_length += b' ' * (HEADER - len(send_length))
client.send(send_length)
client.send(message)
# This is a Python class that creates a server that listens for incoming connections and handles each
# client connection in a separate thread.
myServer = Server()
print("[STARTING] server is starting...")
myServer.start()