-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.py
124 lines (88 loc) · 3.14 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
113
114
115
116
117
118
119
120
121
122
123
124
import asyncio
import logging
import argparse
import pickle
import socket
import sys
import os
from datetime import datetime
clients = []
clients_lock = asyncio.Lock()
# terminal screen clearing function in both types of systems (unix-like & win)
def clear_screen():
if (sys.platform == "win32"):
os.system("cls")
else:
os.system("clear")
def setup_logging():
logging.basicConfig(
level=logging.INFO,
format='[%(asctime)s] [%(levelname)s] %(message)s',
datefmt='%H:%M'
)
def init():
global parser
# creates an argument parser to intercept the arguments that user enters when calling a file
parser = argparse.ArgumentParser()
parser.add_argument("-p", "--port", type=int, help="port of the server socket (0-65535)")
clear_screen()
setup_logging()
asyncio.run(main())
async def main():
ip = socket.gethostbyname(socket.gethostname())
port = parser.parse_args().port or 8383
await Server(ip, port).start()
class Server:
# defines our ip, port, socket to variables
def __init__(self, host, port):
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.host = host
self.port = port
async def start(self):
try:
self.server = await asyncio.start_server(self.new_client, self.host, self.port)
logging.info(f"{self.host}:{self.port}")
logging.info("Waiting for new connections\n")
async with self.server:
await self.server.serve_forever()
except (asyncio.CancelledError, KeyboardInterrupt):
logging.info("Server is closing...")
except socket.error as e:
logging.warning(f"\nSocket Error\n{e}")
finally:
self.server.close()
await self.server.wait_closed()
logging.info("Server closed successfully")
async def new_client(self, reader, writer):
addr = writer.get_extra_info("peername")
await Client(reader, writer, addr[0]).handling()
class Client:
def __init__(self, reader, writer, address):
self.reader = reader
self.writer = writer
self.address = address
async def handling(self):
logging.info(f"Client ({self.address}) connected")
async with clients_lock:
clients.append(self)
while True:
data = await self.reader.read(1024) # getting user data
if data: # checks if data is not nothing
msg = pickle.loads(data)
async with clients_lock:
for client in clients:
if client != self:
client.writer.write(pickle.dumps(msg))
await client.writer.drain()
logging.info(f"{msg.nickname}: {msg.content}")
else:
break
async with clients_lock:
clients.remove(self)
self.writer.close()
await self.writer.wait_closed()
logging.info(f"Client ({self.address}) disconnected")
class Message:
pass
if __name__ == "__main__":
init()