forked from MissKinnian/chat4
-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.py
86 lines (61 loc) · 2.2 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
#!/usr/bin/env python3
"""chatserver server"""
import logging
from argparse import ArgumentParser
from socket import AF_INET, SOCK_STREAM, socket, SOL_SOCKET, SO_REUSEADDR
from threading import Thread
from Crypto.Random.random import getrandbits
from chatlib import handshake, encrypt, decrypt
list_of_clients = []
def client_thread(conn, addr, key):
"""client thread"""
print(f'{addr[0]} connected')
conn_key = handshake(conn, key)
list_of_clients.append((conn, conn_key))
print(f'{addr[0]} handshake ok')
conn.send(encrypt('Welcome to this chatroom!', conn_key))
while True:
try:
message = decrypt(conn.recv(2048), conn_key)
if message:
broadcast(f'<{addr[0]}> {message}', conn)
else:
break
except Exception as exc: # noqa: E722 pylint: disable=broad-except
logging.error('cannot handle message: %s', exc)
break
conn.close()
remove((conn, conn_key))
def broadcast(message, from_conn):
"""send message to all clients except the original sender"""
for client, client_key in list_of_clients:
if client != from_conn:
try:
client.send(encrypt(message, client_key))
except Exception as exc: # noqa: E722 pylint: disable=broad-except
logging.error('cannot broadcast message: %s', exc)
client.close()
remove((client, client_key))
def remove(conn_tuple):
"""remove dead client"""
if conn_tuple in list_of_clients:
list_of_clients.remove(conn_tuple)
def main():
"""main"""
parser = ArgumentParser()
parser.add_argument('--bindaddr', default='')
parser.add_argument('--port', type=int, default=7000)
args = parser.parse_args()
key = getrandbits(32)
server = socket(AF_INET, SOCK_STREAM)
server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
server.bind((args.bindaddr, args.port))
server.listen(100)
while True:
conn, addr = server.accept()
Thread(target=client_thread, args=(conn, addr, key)).start()
for conn in list_of_clients:
conn.close()
server.close()
if __name__ == '__main__':
main()