Язык программирования Python

Передача файла через сокет в Python 3

Следующий код устанавливает соединение клиент-сервер между двумя программами Python с помощью стандартного модуля socket и отправляет файл с клиента на сервер.

Логика передачи файлов содержится в двух функциях: клиент определяет функцию send_file() для отправки файла через сокет и, наоборот, сервер определяет функцию receive_file() для его получения.

Таким образом, вы сможете легко перенести функции из этой статьи в другие программы, которые уже реализуют соединение клиент-сервер.

Код подготовлен для отправки файлов любого формата и любого размера. Требуется Python 3.8 или выше.

Содержание

Сервер:

# server.py import socket import struct def receive_file_size(sck: socket.socket): # Эта функция обеспечивает получение байтов, # указывающих на размер отправляемого файла, # который кодируется клиентом с помощью # struct.pack(), функции, которая генерирует # последовательность байтов, представляющих размер файла. fmt = "<Q" expected_bytes = struct.calcsize(fmt) received_bytes = 0 stream = bytes() while received_bytes < expected_bytes: chunk = sck.recv(expected_bytes - received_bytes) stream += chunk received_bytes += len(chunk) filesize = struct.unpack(fmt, stream)[0] return filesize def receive_file(sck: socket.socket, filename): # Сначала считываем из сокета количество # байтов, которые будут получены из файла. filesize = receive_file_size(sck) # Открываем новый файл для сохранения # полученных данных. with open(filename, "wb") as f: received_bytes = 0 # Получаем данные из файла блоками по # 1024 байта до объема # общего количество байт, сообщенных клиентом. while received_bytes < filesize: chunk = sck.recv(1024) if chunk: f.write(chunk) received_bytes += len(chunk) with socket.create_server(("localhost", 6190)) as server: print("Ожидание клиента...") conn, address = server.accept() print(f"{address[0]}:{address[1]} подключен.") print("Получаем файл...") receive_file(conn, "image-received.png") print("Файл получен.") print("Соединение закрыто.")
Code language: PHP (php)

Клиент

# client.py import os import socket import struct def send_file(sck: socket.socket, filename): # Получение размера файла. filesize = os.path.getsize(filename) # В первую очередь сообщим серверу, # сколько байт будет отправлено. sck.sendall(struct.pack("<Q", filesize)) # Отправка файла блоками по 1024 байта. with open(filename, "rb") as f: while read_bytes := f.read(1024): sck.sendall(read_bytes) with socket.create_connection(("localhost", 6190)) as conn: print("Подключение к серверу.") print("Передача файла...") send_file(conn, "image.png") print("Отправлено.") print("Соединение закрыто.")
Code language: PHP (php)

Чтобы протестировать код, вы должны изменить вызовы send_file() и receive_file(), указав путь к файлу, который вы хотите отправить, и путь к файлу, в котором вы хотите его получить.

В текущем коде это файл image.png, который находится в той же папке, что и два файла Python, и принимается как image-received.png.

После этого запустите сервер:

python server.py
Code language: CSS (css)

Затем, на другом терминале, клиент:

python client.py
Code language: CSS (css)

Вывод сервера будет выглядеть следующим образом:

Ожидание клиента... 127.0.0.1:60331 подключен. Получаем файл... Файл получен. Соединение закрыто.
Code language: CSS (css)

Что касается клиента:

Подключение к серверу. Передача файла... Отправлено. Соединение закрыто.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *