1

I am trying to learn python socket programming (Networks) and I have a function that sends a file but I am not fully understanding each line of this function (can't get my head around it). Could someone please explain line by line what this is doing. I am also unsure why it needs the length of the data to send the file. Also if you can see any improvements to this function as well, thanks.

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)

BarCode
  • 53
  • 1
  • 1
  • 5

1 Answers1

4

This protocol is written to first send the size of the file and then its data. The size is 20 octets (bytes) serialized as "big endian", meaning the most significant byte is sent first. Suppose you had a 1M file,

>>> val = 1000000
>>> val.to_bytes(20, 'big')
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0fB@'

The program sends those 20 bytes and then the file payload itself. The receiver would read the 20 octets, convert that back into a file size and would know exactly how many more octets to receive for the file. TCP is a streaming protocol. It has no idea of message boundaries. Protocols need some way of telling the other side how much data makes up a message and this is a common way to do it.

As an aside, this code has the serious problem that it reads the entire file in one go. Suppose it was huge, this code would crash.

A receiver would look something like the following. This is a rudimentary.

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
tdelaney
  • 73,364
  • 6
  • 83
  • 116
  • thanks for explaining that, would you know how a receive file function would look like based on this? would be helpful – BarCode Jan 10 '21 at 23:47
  • @BarCode, the SO way to say thank you is to vote (if you didn't already do it) and [accept the answer](https://meta.stackexchange.com/a/5235/684852) – anastaciu Apr 17 '21 at 13:21