Как отправить файлы в "чанках" сокетом?

Я пытаюсь отправить большой файл (.avi) через сокет, отправив содержимое файла кусками (немного похоже на торренты). Проблема в том, что скрипт не отправляет файл. У меня нет идей здесь.

Любая помощь или исправление сценария будут очень признательны.

Сервер:

import socket

HOST = ""
PORT = 8050
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((HOST, PORT))
sock.listen(1)
conn, addr = sock.accept() 
print("Connected by ", str(addr))

while 1:
    data = conn.recv(1024)

    if data.decode("utf-8") == 'GET':
        with open(downFile,'rb') as output:
            l = output.read(1024)
            while (l):
                conn.send(l)
                l = output.read(1024)
            output.close()

conn.close()

Клиент:

import socket

HOST = "localhost"
PORT = 8050
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((HOST,PORT))

while 1:

    message = input()
    sock.send(bytes(message,'UTF-8'))

    conn.send(str.encode('GET'))
    with open(downFile, 'wb+') as output:
        while True:
            rec = str(sock.recv(1024), "utf-8")
            if not rec:
                break
            output.write(rec)
        output.close()
    print('Success!')
sock.close()

1 ответ

Вот работающий клиент и сервер, который должен продемонстрировать передачу файла через сокет. Я сделал некоторые предположения о том, что должен делать ваш код, например, я предположил, что исходное сообщение, отправляемое клиентом на сервер, должно быть именем файла для загрузки.

Код также включает некоторые дополнительные функции, позволяющие серверу возвращать клиенту сообщение об ошибке. Перед запуском кода убедитесь, что каталог указан DOWNLOAD_DIR существует.

Клиент:

import socket
import sys
import os

HOST = "localhost"
PORT = 8050
BUF_SIZE = 4096
DOWNLOAD_DIR = "downloads"

def download_file(s, down_file):
    s.send(str.encode("GET\n" + down_file))
    rec = s.recv(BUF_SIZE)
    if not rec:
        return "server closed connection"

    if rec[:2].decode("utf-8") != 'OK':
        return "server error: " + rec.decode("utf-8")

    rec = rec[:2]
    if DOWNLOAD_DIR:
        down_file = os.path.join(DOWNLOAD_DIR, down_file)
    with open(down_file, 'wb') as output:
        if rec:
            output.write(rec)
        while True:
            rec = s.recv(BUF_SIZE)
            if not rec:
                break
            output.write(rec)

    print('Success!')
    return None

if DOWNLOAD_DIR and not os.path.isdir(DOWNLOAD_DIR):
    print('no such directory "%s"' % (DOWNLOAD_DIR,), file=sys.stderr)
    sys.exit(1)

while 1:
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    try:
        sock.connect((HOST, PORT))
    except Exception as e:
        print("cannot connect to server:", e, file=sys.stderr)
        break

    file_name = input("\nFile to get: ")
    if not file_name:
        sock.close()
        break

    err = download_file(sock, file_name)
    if err:
        print(err, file=sys.stderr)
    sock.close()

Сервер:

import socket
import sys
import os

HOST = ""
PORT = 8050
BUF_SIZE = 4096

def recv_dl_file(conn):
    data = conn.recv(1024)
    if not data:
        print("Client finished")
        return None, None

    # Get command and filename
    try:
        cmd, down_file = data.decode("utf-8").split("\n")
    except:
        return None, "cannot parse client request"
    if cmd != 'GET':
        return None, "unknown command: " + cmd

    print(cmd, down_file)
    if not os.path.isfile(down_file):
        return None, 'no such file "%s"'%(down_file,)

    return down_file, None


def send_file(conn):
    down_file, err = recv_dl_file(conn)
    if err:
        print(err, file=sys.stderr)
        conn.send(bytes(err, 'utf-8'))
        return True

    if not down_file:
        return False # client all done

    # Tell client it is OK to receive file
    sent = conn.send(bytes('OK', 'utf-8'))

    total_sent = 0
    with open(down_file,'rb') as output:
        while True:
            data = output.read(BUF_SIZE)
            if not data:
                break
            conn.sendall(data)
            total_sent += len(data)

    print("finished sending", total_sent, "bytes")
    return True


sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((HOST, PORT))
sock.listen(1)
keep_going = 1
while keep_going:
    conn, addr = sock.accept()
    print("Connected by", str(addr))
    keep_going = send_file(conn)
    conn.close() # close clien connection
    print()

sock.close() # close listener
Другие вопросы по тегам