# client.py
import os
import socket
import threading
import sys
import time
REQUEST_DOWNLOAD_FILE = "input.txt"
DOWNLOAD_FOLDER = "data"
BUFFER_SIZE = 4096
PORT = 9876
lock = threading.Lock()
last_used_line_in_terminal = 0
...
def display_progress_download(base_line, part_num, percent):
with lock:
target_line = base_line + part_num
sys.stdout.write(f'\033[{target_line}H')
sys.stdout.write('\033[2K')
sys.stdout.write(f"Part {part_num} - Progress: {percent:.2f}% / 100%\r")
sys.stdout.flush()
time.sleep(0.01)
def download_part(HOST, PORT, file_name, part_num, start, end, base_line, part_size):
client = None
try:
client = create_connection_to_server(HOST, PORT)
if not client:
return False
client.recv(BUFFER_SIZE)
request = f"{file_name}|{start}-{end}".encode()
client.sendall(request)
part_path = f"./{DOWNLOAD_FOLDER}/{file_name}.part{part_num}"
with open(part_path, "wb") as f:
received = 0
while received < part_size:
chunk_size = min(BUFFER_SIZE, part_size - received)
data = client.recv(chunk_size)
if not data:
raise ConnectionError(f"Connection lost at {received} bytes")
f.write(data)
received += len(data)
percent = min(received / part_size * 100, 100)
display_progress_download(base_line, part_num, percent)
return True
except Exception as e:
print(f"Error downloading part {part_num}: {e}")
return False
finally:
if client:
client.close()
def merge_parts(file_name, parts):
output_path = f"./{DOWNLOAD_FOLDER}/{file_name}"
try:
with open(output_path, "wb") as output_file:
for part_path in parts:
with open(part_path, "rb") as part_file:
while chunk := part_file.read(BUFFER_SIZE):
output_file.write(chunk)
os.remove(part_path)
return True
except Exception as e:
return False
def download_file(HOST, PORT, file_name, file_size):
global last_used_line_in_terminal
os.makedirs(DOWNLOAD_FOLDER, exist_ok=True)
threads = []
parts = []
base_line = last_used_line_in_terminal + 1
last_used_line_in_terminal = base_line + 6
print(f"\033[{base_line}HDownloading {file_name}...\n")
for i in range(4):
start = i * (file_size // 4)
end = file_size if i == 3 else (i + 1) * (file_size // 4)
part_size = end - start
thread = threading.Thread(target=download_part, args=(HOST, PORT, file_name, i + 1, start, end, base_line, part_size))
threads.append(thread)
thread.start()
for thread in threads:
thread.join()
for i in range(4):
part_path = f"./{DOWNLOAD_FOLDER}/{file_name}.part{i + 1}"
if not os.path.exists(part_path):
return False
parts.append(part_path)
success = merge_parts(file_name, parts)
try:
merged_file_size = os.path.getsize(f"./{DOWNLOAD_FOLDER}/{file_name}")
if success and merged_file_size == file_size:
print(f"\033[{base_line + 5}HDownload {file_name} completed successfully!\n")
print(f"\033[{base_line + 6}H" + "-" * 40)
else:
print(f"\033[{base_line + 5}HDownload {file_name} errors! Expected:{file_size}, Got:{merged_file_size}\n")
except FileNotFoundError:
print(f"\033[{base_line + 5}HDownload of {file_name} failed! Merged file not found.")
return success
Вот мой клиентский и серверный код. Он будет загружать файлы с сервера клиенту. Клиент создаст 4 параллельных соединения с сервером, каждое соединение будет отвечать за загрузку части исходного размера файла (при этом исходный размер файла разделен на 4), и мне нужно отобразить их прогресс на экране. .
Теперь вопросы, которые я хочу задать.
Я использовал Escape-код ANSI, чтобы отобразить прогресс, перемещая курсор, удаление старого номера и запись нового номера, это работает довольно хорошо, но если терминалу не хватает длины, он будет перезаписан в последней строке так же, как и на терминале. Я хочу посмотреть, есть ли способ отобразить еще 4 потока или исправить эту ошибку.
example display process
Host Name: 127.0.0.1
Available files:
genshin.png|5980541
arya.gif|3707944
jinx.png|2445272
alime.jpeg|23765
avt.jpeg|51573
Downloading arya.gif...
Part 1 - Progress: 100.00% / 100%
Part 2 - Progress: 100.00% / 100%
Part 3 - Progress: 100.00% / 100%
Part 4 - Progress: 100.00% / 100%
Download completed successfully for arya.gif!
----------------------------------------
Downloading jinx.png...
Part 1 - Progress: 100.00% / 100%
Part 2 - Progress: 100.00% / 100%
Part 3 - Progress: 100.00% / 100%
Part 4 - Progress: 100.00% / 100%
Download completed successfully for jinx.png!
Я использовал библиотеку журналов Python для проверки байтов, передаваемых между сервером и клиентом, и обнаружил, что они, похоже, не находятся на в то же время. В частности, следующим образом:
2024-12-15 00:33:37,379 - INFO - Received: 2260992 bytes in part 1 of vangoh.jpg
2024-12-15 00:33:37,387 - INFO - Received: 2342912 bytes in part 1 of vangoh.jpg
2024-12-15 00:33:37,395 - INFO - Received: 2424832 bytes in part 1 of vangoh.jpg
2024-12-15 00:33:37,396 - INFO - Received: 81816 bytes in part 2 of vangoh.jpg
2024-12-15 00:33:37,404 - INFO - Received: 2506752 bytes in part 1 of vangoh.jpg
2024-12-15 00:33:37,412 - INFO - Received: 163736 bytes in part 2 of vangoh.jpg
2024-12-15 00:33:37,420 - INFO - Received: 2588672 bytes in part 1 of vangoh.jpg
Это часть процесса передачи байтов, и когда часть 1 передаст около 80%, часть 2 начнет передачу, при этом я хочу, чтобы все 4 части передавали параллельно одновременно время (разница может быть, но она небольшая), из-за этого мой прогресс иногда отображает часть 1 примерно на 80/100% до того, как начинает загружаться часть 2. Я хочу посмотреть, как исправить эту ошибку.
Возможно, статья немного длинная, но я надеюсь, что все меня поддержат, не забудьте сохранить мои функции без изменений. Большое спасибо всем.
Я пробовал распечатать прогресс, но если терминалу недостаточно длины, он будет перезаписан в конце.
Я также пробовал загрузить файл, разделив его его на 4 параллельные части, но 4 потока не выполняются одновременно, но иногда часть 2 появляется перед частью 1, я хочу, чтобы все 4 запускались одновременно.
У меня есть две проблемы, требующие помощи ниже. Передача файловых сокетов Python и многопоточность [code]# server.py import os import socket import threading
with open(text_file, 'r') as f: file_list = f.read() server.send(file_list.encode())
while True: request = server.recv(BUFFER_SIZE).decode().strip() if not request: break
if '|' not in request: file_path = os.path.join(resources_dir, request) if os.path.isfile(file_path): file_size = os.path.getsize(file_path) server.send(str(file_size).encode()) else: server.send(f"File {request} not found.".encode()) continue
parts = request.split('|') if len(parts) != 2: server.send("Invalid request.".encode()) continue
file_name, range_str = parts start, end = map(int, range_str.split('-')) file_path = os.path.join(resources_dir, file_name)
if not os.path.isfile(file_path): server.send(f"File {file_name} not found.".encode()) continue
with file_lock: with open(file_path, 'rb') as f: f.seek(start) remaining = end - start
while remaining > 0: chunk_size = min(BUFFER_SIZE, remaining) chunk = f.read(chunk_size) if not chunk: break server.sendall(chunk) remaining -= len(chunk)
except ConnectionResetError: print(f"Connection reset by peer {addr}") except Exception as e: print(f"Error handling client {addr}: {e}") finally: server.close()
def run_server(): write_text() try: while True: server, addr = init_server.accept() print(f"Connected by {addr}") thread = threading.Thread(target=handle_client, args=(server, addr)) thread.daemon = True thread.start() except KeyboardInterrupt: print("\nServer is shutting down...") finally: server.close()
if __name__ == "__main__": run_server() [/code] [code]# client.py import os import socket import threading import sys import time
part_path = f"./{DOWNLOAD_FOLDER}/{file_name}.part{part_num}" with open(part_path, "wb") as f: received = 0 while received < part_size: chunk_size = min(BUFFER_SIZE, part_size - received) data = client.recv(chunk_size) if not data: raise ConnectionError(f"Connection lost at {received} bytes") f.write(data) received += len(data) percent = min(received / part_size * 100, 100) display_progress_download(base_line, part_num, percent) return True
except Exception as e: print(f"Error downloading part {part_num}: {e}") return False finally: if client: client.close()
def merge_parts(file_name, parts): output_path = f"./{DOWNLOAD_FOLDER}/{file_name}" try: with open(output_path, "wb") as output_file: for part_path in parts: with open(part_path, "rb") as part_file: while chunk := part_file.read(BUFFER_SIZE): output_file.write(chunk) os.remove(part_path) return True except Exception as e: return False
def download_file(HOST, PORT, file_name, file_size): global last_used_line_in_terminal os.makedirs(DOWNLOAD_FOLDER, exist_ok=True)
[/code] Вот мой клиентский и серверный код. Он будет загружать файлы с сервера клиенту. Клиент создаст 4 параллельных соединения с сервером, каждое соединение будет отвечать за загрузку части исходного размера файла (при этом исходный размер файла разделен на 4), и мне нужно отобразить их прогресс на экране. . Теперь вопросы, которые я хочу задать. [list] [*]Я использовал Escape-код ANSI, чтобы отобразить прогресс, перемещая курсор, удаление старого номера и запись нового номера, это работает довольно хорошо, но если терминалу не хватает длины, он будет перезаписан в последней строке так же, как и на терминале. Я хочу посмотреть, есть ли способ отобразить еще 4 потока или исправить эту ошибку. [/list] [code]example display process Host Name: 127.0.0.1 Available files: genshin.png|5980541 arya.gif|3707944 jinx.png|2445272 alime.jpeg|23765 avt.jpeg|51573
Downloading arya.gif... Part 1 - Progress: 100.00% / 100% Part 2 - Progress: 100.00% / 100% Part 3 - Progress: 100.00% / 100% Part 4 - Progress: 100.00% / 100% Download completed successfully for arya.gif! ---------------------------------------- Downloading jinx.png... Part 1 - Progress: 100.00% / 100% Part 2 - Progress: 100.00% / 100% Part 3 - Progress: 100.00% / 100% Part 4 - Progress: 100.00% / 100% Download completed successfully for jinx.png! [/code] [list] [*]Я использовал библиотеку журналов Python для проверки байтов, передаваемых между сервером и клиентом, и обнаружил, что они, похоже, не находятся на в то же время. В частности, следующим образом: [/list] [code]2024-12-15 00:33:37,379 - INFO - Received: 2260992 bytes in part 1 of vangoh.jpg 2024-12-15 00:33:37,387 - INFO - Received: 2342912 bytes in part 1 of vangoh.jpg 2024-12-15 00:33:37,395 - INFO - Received: 2424832 bytes in part 1 of vangoh.jpg 2024-12-15 00:33:37,396 - INFO - Received: 81816 bytes in part 2 of vangoh.jpg 2024-12-15 00:33:37,404 - INFO - Received: 2506752 bytes in part 1 of vangoh.jpg 2024-12-15 00:33:37,412 - INFO - Received: 163736 bytes in part 2 of vangoh.jpg 2024-12-15 00:33:37,420 - INFO - Received: 2588672 bytes in part 1 of vangoh.jpg [/code] Это часть процесса передачи байтов, и когда часть 1 передаст около 80%, часть 2 начнет передачу, при этом я хочу, чтобы все 4 части передавали параллельно одновременно время (разница может быть, но она небольшая), из-за этого мой прогресс иногда отображает часть 1 примерно на 80/100% до того, как начинает загружаться часть 2. Я хочу посмотреть, как исправить эту ошибку. Возможно, статья немного длинная, но я надеюсь, что все меня поддержат, не забудьте сохранить мои функции без изменений. Большое спасибо всем. Я пробовал распечатать прогресс, но если терминалу недостаточно длины, он будет перезаписан в конце. Я также пробовал загрузить файл, разделив его его на 4 параллельные части, но 4 потока не выполняются одновременно, но иногда часть 2 появляется перед частью 1, я хочу, чтобы все 4 запускались одновременно.
Во-первых, я все еще новичок в программировании, поэтому, пожалуйста, не ругайте меня за то, что я что-то делаю неправильно. Все в коде — это то, чему я научился на уроках.
Итак, я создал игру «Крестики-нолики», и, как сказано в названии, ход...
У меня есть запрос относительно двух операций Redis, выполняемых в одной команде, например команды String и команды Hash, одновременно
для получения их значений с сервера Redis.
SET key1 value1
SET key2 value2
HSET key3 field3 value3
HSET key4...
Используя Apache Commons VFS, как мне контролировать ход передачи файла. Мне нужно быть в состоянии сделать это с помощью загрузки и загрузки. Мне также необходимо отслеживать прогресс над HTTP, FTP, SFTP и FTPS. Я не могу найти ничего в...
Используя Apache Commons VFS, как мне контролировать ход передачи файла. Мне нужно быть в состоянии сделать это с помощью загрузки и загрузки. Мне также необходимо отслеживать прогресс над HTTP, FTP, SFTP и FTPS. Я не могу найти ничего в...
Я использую Elementor Pro, который обеспечивает виджет цикла, который позволяет нам пройти через результаты WP_QUERY.
Виджет петли поставляется со встроенной функцией страниц. /> В дополнение к функциональности страниц по умолчанию, я хотел...