summaryrefslogtreecommitdiff
path: root/day4
diff options
context:
space:
mode:
Diffstat (limited to 'day4')
-rw-r--r--day4/task4/client.py194
-rw-r--r--day4/task4/client_class.py134
-rw-r--r--day4/task4/server.py57
3 files changed, 123 insertions, 262 deletions
diff --git a/day4/task4/client.py b/day4/task4/client.py
index bc4a40f..b6f0ab8 100644
--- a/day4/task4/client.py
+++ b/day4/task4/client.py
@@ -12,138 +12,124 @@ except ImportError:
TQDM = False
-def pack_data(data):
- encoded = data.encode()
- return struct.pack('I', len(encoded)) + encoded
-
-
-def handle_input(data):
- cmd, args = data.split(' ', maxsplit=1)
-
- if cmd == 'get':
- make_get_request(args)
-
- elif cmd == 'cp':
- paths = args.split()
- if len(paths) != 2:
- raise ValueError('Неверное количество путей в параметрах.')
-
- src, dest = paths
-
- # Если файл не присутствует в БД, то предварительно его загружаем
- status = 0
- if src not in db:
- status = make_get_request(src)
-
- if status == 0:
- with open(dest, 'wb') as f:
- f.write(db[src])
-
- else:
- raise ValueError('Команда не распознана')
+DATATYPE_SIZE = 4 # int
+CHUNK_SIZE = 4096000
+HOST, PORT = ADDR = 'localhost', 6000
-def make_get_request(path):
- packet = pack_data(json.dumps({'method': 'get', 'path': path}))
- sock.sendall(packet)
- response = get_response()
- return handle_response(response)
+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)
-def parse_response(data):
- return json.loads(data.decode())
+ except ConnectionRefusedError:
+ print('Не удалось подключиться к серверу. Следующая попытка через 3 секунды...')
+ sleep(3)
+ else:
+ break
-def get_response():
- buffer = b''
- while len(buffer) < DATATYPE_SIZE:
- data = sock.recv(DATATYPE_SIZE - len(buffer))
- if not data:
- raise ConnectionError('Connection was closed')
+ else:
+ print('Не удалось подключиться к серверу через 10 попыток.\nОстанавливаемся...')
+ self.server.close()
- buffer += data
+ def start(self):
+ while True:
+ try:
+ data = input('Введите команду:\n')
+ self.handle_input(data)
- size_packed, buffer = buffer[:DATATYPE_SIZE], buffer[DATATYPE_SIZE:]
- if not size_packed:
- raise ConnectionError('Connection was closed')
+ except ValueError as err:
+ print(err)
- (size,) = struct.unpack('I', size_packed)
- data = sock.recv(size - len(buffer))
- return parse_response(buffer + data)
+ except KeyboardInterrupt:
+ break
+ self.server.close()
-def download_file(filesize):
- data = b''
+ def handle_input(self, data):
+ cmd, args = data.split(' ', maxsplit=1)
- 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
+ if cmd == 'get':
+ self.download_file(args)
- return data
+ elif cmd == 'cp':
+ paths = args.split()
+ if len(paths) != 2:
+ raise ValueError('Неверное количество путей в параметрах.')
+ src, dest = paths
-def handle_response(data):
- if data['status'] == 0:
- print(f'Загружаем файл размером {data["size"]} байт...')
- file_data = download_file(data['size'])
- db[data['path']] = file_data
- print('Загрузка завершена')
+ # Если файл не присутствует в БД, то предварительно его загружаем
+ if src not in self.db:
+ self.download_file(src)
- elif data['status'] == 1:
- print(data['reason'])
+ # При любых ошибках при загрузке файла download_file выкинет исключение и исполнение
+ # не дойдет до этого блока, поэтому можно не проверять наличие src в БД
+ with open(dest, 'wb') as f:
+ f.write(self.db[src])
- elif data['status'] == 2:
- print('Неизвестная ошибка:')
- print(data['reason'])
+ else:
+ raise ValueError('Команда не распознана')
- return data['status']
+ 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
-def try_connect():
- cnt = 0
- sock = socket.socket()
- while cnt < 10:
- try:
- cnt += 1
- sock.connect(ADDR)
+ print('Загрузка завершена')
- except ConnectionRefusedError:
- print('Не удалось подключиться к серверу. Следующая попытка через 3 секунды...')
- sleep(3)
+ elif response['status'] == 1:
+ raise ValueError(response['reason'])
- else:
- return sock
+ elif response['status'] == 2:
+ raise ValueError(f'Неизвестная ошибка: {response["reason"]}')
- else:
- print('Не удалось подключиться к серверу через 10 попыток.\nОстанавливаемся...')
- sock.close()
- return
+ 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''
-HOST, PORT = ADDR = 'localhost', 6000
-DATATYPE_SIZE = 4 # int
-CHUNK_SIZE = 4096000
+ # С копипастой надо бы что-то сделать, но я не знаю что
+ 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')
-sock = try_connect()
-if sock is None:
- quit()
+ 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
-db = shelve.open('backdoor.db')
+ @staticmethod
+ def pack_str(data):
+ encoded = data.encode()
+ return struct.pack('I', len(encoded)) + encoded
-while True:
- try:
- data = input('Введите команду:\n')
- handle_input(data)
+ @staticmethod
+ def parse_response(data):
+ return json.loads(data.decode())
- except KeyboardInterrupt:
- break
-sock.close()
+if __name__ == '__main__':
+ client = Client(HOST, PORT)
+ client.start()
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()
diff --git a/day4/task4/server.py b/day4/task4/server.py
index fb88629..d013b35 100644
--- a/day4/task4/server.py
+++ b/day4/task4/server.py
@@ -3,6 +3,11 @@ import struct
import json
+HOST, PORT = ADDR = '0.0.0.0', 6000
+CHUNK_SIZE = 4096000
+DATATYPE_SIZE = 4 # int
+
+
def pack_str(data: str):
encoded = data.encode()
return struct.pack('I', len(encoded)) + encoded
@@ -54,14 +59,15 @@ def handle_request(data, connection):
def get_data(connection):
buffer = b''
- while len(buffer) < 4:
- data = connection.recv(4 - len(buffer))
+ # Считываем размер пакета
+ while len(buffer) < DATATYPE_SIZE:
+ data = connection.recv(DATATYPE_SIZE - len(buffer))
if not data:
raise ConnectionError('Connection was closed')
buffer += data
- size_packed, buffer = buffer[:4], buffer[4:]
+ size_packed, buffer = buffer[:DATATYPE_SIZE], buffer[DATATYPE_SIZE:]
if not size_packed:
raise ConnectionError('Connection was closed')
@@ -93,24 +99,27 @@ def handle_connection(connection, address):
handle_request(data.decode(), connection)
-HOST, PORT = ADDR = '0.0.0.0', 6000
-CHUNK_SIZE = 4096000
-sock = socket.socket()
-sock.bind(ADDR)
-sock.listen(5)
-
-while True:
- print('Listening for new connections...')
- try:
- connection, address = sock.accept()
- 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()
- print('Server stopped')
- break
+def main():
+ sock = socket.socket()
+ sock.bind(ADDR)
+ sock.listen(5)
+
+ while True:
+ print('Listening for new connections...')
+ try:
+ connection, address = sock.accept()
+ 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()
+ print('Server stopped')
+ break
+
+
+if __name__ == '__main__':
+ main()