#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, лучший способ поблагодарить вас — проголосовать (если вы еще этого не сделали) и принять ответ