сокеты python отправляют объяснение функции файла

#python #sockets #python-sockets

#python #сокеты #python-сокеты

Вопрос:

Я пытаюсь изучить программирование сокетов на python (сети), и у меня есть функция, которая отправляет файл, но я не до конца понимаю каждую строку этой функции (не могу разобраться в этом).). Не мог бы кто-нибудь, пожалуйста, объяснить построчно, что это делает. Я также не уверен, зачем ему нужна длина данных для отправки файла. Также, если вы видите какие-либо улучшения в этой функции, спасибо.

 def send_file(socket, filename):
    with open(filename, "rb") as x:
        data = x.read()
        length_data = len(data)
        try:
            socket.sendall(length_data.to_bytes(20, 'big'))
            socket.sendall(data)
        except Exception as error:
            print("Error", error)

 

Ответ №1:

Этот протокол написан для того, чтобы сначала отправить размер файла, а затем его данные. Размер составляет 20 октетов (байт), сериализованных как «big endian», что означает, что самый значимый байт отправляется первым. Предположим, у вас был файл размером 1 млн.,

 >>> val = 1000000
>>> val.to_bytes(20, 'big')
b'x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x0fB@'
 

Программа отправляет эти 20 байтов, а затем саму полезную нагрузку файла. Получатель прочитает 20 октетов, преобразует их обратно в размер файла и будет точно знать, сколько еще октетов нужно получить для файла. TCP — это потоковый протокол. Он не имеет представления о границах сообщений. Протоколам нужен какой-то способ сообщить другой стороне, сколько данных составляет сообщение, и это обычный способ сделать это.

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

Получатель будет выглядеть примерно следующим образом. Это элементарно.

 import io
def recv_exact(skt, count):
    buf = io.BytesIO()
    while count:
        data = skt.recv(count)
        if not data:
            return b"" # socket closed
        buf.write(data)
        count -= len(data)
    return buf.getvalue()

def recv_file(skt):
    data = recv_exact(skt, 20)
    if not data:
        return b""
    file_size = int.from_bytes(data, "big")
    file_bytes = recv_exact(skt, file_size)
    return file_bytes
 

Комментарии:

1. спасибо за объяснение, знаете ли вы, как будет выглядеть функция получения файла на основе этого? было бы полезно

2. @BarCode, лучший способ поблагодарить вас — проголосовать (если вы еще этого не сделали) и принять ответ