diff options
Diffstat (limited to 'day4/task4/client_class.py')
| -rw-r--r-- | day4/task4/client_class.py | 134 |
1 files changed, 0 insertions, 134 deletions
diff --git a/day4/task4/client_class.py b/day4/task4/client_class.py deleted file mode 100644 index 854e5e2..0000000 --- a/day4/task4/client_class.py +++ /dev/null @@ -1,134 +0,0 @@ -import socket -from time import sleep -import struct -import json -import shelve - -try: - from tqdm import tqdm - TQDM = True -except ImportError: - print('Для вывода прогресса загрузки файлов установите библиотеку tqdm') - TQDM = False - - -DATATYPE_SIZE = 4 # int -CHUNK_SIZE = 4096000 -HOST, PORT = ADDR = 'localhost', 6000 - - -class Client: - def __init__(self, server_host, server_port): - self.server = socket.socket() - self.db = shelve.open('backdoor.db') - - address = server_host, server_port - cnt = 0 - while cnt < 10: - try: - cnt += 1 - self.server.connect(address) - - except ConnectionRefusedError: - print('Не удалось подключиться к серверу. Следующая попытка через 3 секунды...') - sleep(3) - - else: - break - - else: - print('Не удалось подключиться к серверу через 10 попыток.\nОстанавливаемся...') - self.server.close() - - def start(self): - while True: - try: - data = input('Введите команду:\n') - self.handle_input(data) - - except ValueError as err: - print(err) - - except KeyboardInterrupt: - break - - self.server.close() - - def handle_input(self, data): - cmd, args = data.split(' ', maxsplit=1) - - if cmd == 'get': - self.download_file(args) - - elif cmd == 'cp': - paths = args.split() - if len(paths) != 2: - raise ValueError('Неверное количество путей в параметрах.') - - src, dest = paths - - # Если файл не присутствует в БД, то предварительно его загружаем - if src not in self.db: - self.download_file(src) - - # При любых ошибках при загрузке файла download_file выкинет исключение и исполнение - # не дойдет до этого блока, поэтому можно не проверять наличие src в БД - with open(dest, 'wb') as f: - f.write(self.db[src]) - - else: - raise ValueError('Команда не распознана') - - def download_file(self, path): - response = self.make_get_request(path) - if response['status'] == 0: - print(f'Загружаем файл размером {response["size"]} байт...') - - file_data = self.receive_data(int(response['size']), use_tqdm=True) - self.db[path] = file_data - - print('Загрузка завершена') - - elif response['status'] == 1: - raise ValueError(response['reason']) - - elif response['status'] == 2: - raise ValueError(f'Неизвестная ошибка: {response["reason"]}') - - def make_get_request(self, path): - packet = Client.pack_str(json.dumps({'method': 'get', 'path': path})) - self.server.sendall(packet) - return Client.parse_response(self.receive_data(DATATYPE_SIZE)) - - def receive_data(self, data_size, use_tqdm=False): - data = b'' - - # С копипастой надо бы что-то сделать, но я не знаю что - if not use_tqdm or not TQDM: - while len(data) < data_size: - (packet_size,) = struct.unpack('I', self.server.recv(DATATYPE_SIZE)) - data += self.server.recv(packet_size) - if not data: - raise ConnectionError('Connection was closed') - - elif TQDM: - for count in tqdm(range(0, data_size, CHUNK_SIZE)): - (packet_size,) = struct.unpack('I', self.server.recv(DATATYPE_SIZE)) - data += self.server.recv(packet_size) - if not data: - raise ConnectionError('Connection was closed') - - return data - - @staticmethod - def pack_str(data): - encoded = data.encode() - return struct.pack('I', len(encoded)) + encoded - - @staticmethod - def parse_response(data): - return json.loads(data.decode()) - - -client = Client(HOST, PORT) -client.start() |