From 7e591a381db30bfcd374ebdffdc058f8bbfd24ed Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 22 Apr 2019 21:00:47 +0400 Subject: =?UTF-8?q?=D0=A7=D0=B5=D1=82=D0=B2=D0=B5=D1=80=D1=82=D0=B0=D1=8F?= =?UTF-8?q?=20=D0=B7=D0=B0=D0=B4=D0=B0=D1=87=D0=B0=20=D0=B7=D0=B0=D0=B2?= =?UTF-8?q?=D0=B5=D1=80=D1=88=D0=B5=D0=BD=D0=B0.=20=D0=98=D1=81=D0=BF?= =?UTF-8?q?=D0=BE=D0=BB=D1=8C=D0=B7=D1=83=D0=B5=D1=82=D1=81=D1=8F=20=D0=BD?= =?UTF-8?q?=D0=B5=20=D0=BE=D0=B1=D1=8F=D0=B7=D0=B0=D1=82=D0=B5=D0=BB=D1=8C?= =?UTF-8?q?=D0=BD=D0=B0=D1=8F=20=D0=B1=D0=B8=D0=B1=D0=BB=D0=B8=D0=BE=D1=82?= =?UTF-8?q?=D0=B5=D0=BA=D0=B0=20tqdm=20(=D1=87=D1=82=D0=BE=D0=B1=D1=8B=20?= =?UTF-8?q?=D0=B1=D1=8B=D0=BB=D0=BE=20=D0=BA=D1=80=D0=B0=D1=81=D0=B8=D0=B2?= =?UTF-8?q?=D0=BE)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- day4/task4/client.py | 76 ++++++++++++++++++++++++++++++++-------------------- day4/task4/server.py | 10 +++++-- 2 files changed, 55 insertions(+), 31 deletions(-) (limited to 'day4') diff --git a/day4/task4/client.py b/day4/task4/client.py index 33ea084..bc4a40f 100644 --- a/day4/task4/client.py +++ b/day4/task4/client.py @@ -4,40 +4,60 @@ import struct import json import shelve +try: + from tqdm import tqdm + TQDM = True +except ImportError: + print('Для вывода прогресса загрузки файлов установите библиотеку tqdm') + TQDM = False + def pack_data(data): encoded = data.encode() return struct.pack('I', len(encoded)) + encoded -def prepare_data(data): +def handle_input(data): cmd, args = data.split(' ', maxsplit=1) if cmd == 'get': - return json.dumps({'method': 'get', 'path': args}) + make_get_request(args) elif cmd == 'cp': paths = args.split() if len(paths) != 2: raise ValueError('Неверное количество путей в параметрах.') - src, dest = args.split() + + src, dest = paths + + # Если файл не присутствует в БД, то предварительно его загружаем + status = 0 if src not in db: - return json.dumps({'method': 'get_cp', 'path': src}) - with open(dest, 'wb') as f: - f.write(db[src]) + status = make_get_request(src) + + if status == 0: + with open(dest, 'wb') as f: + f.write(db[src]) else: raise ValueError('Команда не распознана') +def make_get_request(path): + packet = pack_data(json.dumps({'method': 'get', 'path': path})) + sock.sendall(packet) + response = get_response() + return handle_response(response) + + def parse_response(data): return json.loads(data.decode()) -def get_response(connection): +def get_response(): buffer = b'' while len(buffer) < DATATYPE_SIZE: - data = connection.recv(DATATYPE_SIZE - len(buffer)) + data = sock.recv(DATATYPE_SIZE - len(buffer)) if not data: raise ConnectionError('Connection was closed') @@ -48,25 +68,31 @@ def get_response(connection): raise ConnectionError('Connection was closed') (size,) = struct.unpack('I', size_packed) - data = connection.recv(size - len(buffer)) + data = sock.recv(size - len(buffer)) return parse_response(buffer + data) -def download_file(filesize, connection): +def download_file(filesize): data = b'' - count = 0 - while count < filesize: - (size,) = struct.unpack('I', connection.recv(DATATYPE_SIZE)) - data += connection.recv(size) - count += size + + if TQDM: + for count in tqdm(range(0, filesize, CHUNK_SIZE)): + (size,) = struct.unpack('I', sock.recv(DATATYPE_SIZE)) + data += sock.recv(size) + else: + count = 0 + while count < filesize: + (size,) = struct.unpack('I', sock.recv(DATATYPE_SIZE)) + data += sock.recv(size) + count += size return data -def handle_response(data, connection): +def handle_response(data): if data['status'] == 0: print(f'Загружаем файл размером {data["size"]} байт...') - file_data = download_file(data['size'], connection) + file_data = download_file(data['size']) db[data['path']] = file_data print('Загрузка завершена') @@ -77,6 +103,8 @@ def handle_response(data, connection): print('Неизвестная ошибка:') print(data['reason']) + return data['status'] + def try_connect(): cnt = 0 @@ -101,6 +129,7 @@ def try_connect(): HOST, PORT = ADDR = 'localhost', 6000 DATATYPE_SIZE = 4 # int +CHUNK_SIZE = 4096000 sock = try_connect() if sock is None: @@ -112,20 +141,9 @@ db = shelve.open('backdoor.db') while True: try: data = input('Введите команду:\n') - data = prepare_data(data) - if data is None: - continue + handle_input(data) except KeyboardInterrupt: break - except ValueError as err: - print(err) - - else: - packet = pack_data(data) - sock.sendall(packet) - response = get_response(sock) - handle_response(response, sock) - sock.close() diff --git a/day4/task4/server.py b/day4/task4/server.py index 980eebc..fb88629 100644 --- a/day4/task4/server.py +++ b/day4/task4/server.py @@ -35,18 +35,21 @@ def handle_request(data, connection): # Я знаю, что это плохо, но сервер не должен падать, # а других ошибок я не смог вспомнить except Exception as e: - header = json.dumps({'status': 2, 'reason': str(e)}) + header = json.dumps({'status': 2, 'reason': f'{type(e)}: {e}'}) connection.sendall(pack_str(header)) else: length = len(file_data) header = json.dumps({'status': 0, 'size': length, 'path': request['path']}) connection.sendall(pack_str(header)) + print(f'Started sending file of size {length} bytes...') i = 0 while i < length: packet = pack_bytes(file_data[i: i + CHUNK_SIZE]) connection.sendall(packet) i += CHUNK_SIZE + print(i / length * 100, '%') + print(f'Transmission ended') def get_data(connection): @@ -91,7 +94,7 @@ def handle_connection(connection, address): HOST, PORT = ADDR = '0.0.0.0', 6000 -CHUNK_SIZE = 4096 +CHUNK_SIZE = 4096000 sock = socket.socket() sock.bind(ADDR) sock.listen(5) @@ -103,6 +106,9 @@ while True: print(f'Got a connection from {address[0]}') handle_connection(connection, address) + except ConnectionResetError: + print(f'Connection with {address[0]} was unexpectedly closed') + except KeyboardInterrupt: print('Stopping server...') sock.close() -- cgit v1.2.3