0

I wrote a function to send a file using a socket. It sends first the size of the file and then sends blocks of 9999 bytes to the client until the file ends. the problem is when the server reads the file, the file ends too fast. for example, for a file with 180,000 bytes, it ends after 2 blocks. I couldn't understand why this happens and I tried to run the read on this file in the terminal and it worked fine but here it doesn't. As much as I know the problem is supposed to be in the sever because when I checked, the server doesn't send all the data he is supposed to send because after about 2 read() calls it returns an empty string even though most of the file haven't been read.

here is the server code:

MAX_LENGTH_OF_SEND = 9999
def send_file(path, client_socket):
    """send a file to the client. if succeeded return success, else return error massage
    :param path: path of the file to send
    :param client_socket: the socket of the client to send to
    :return: if success return 'success sending a file' else, return error massage
    """
    try:
        size  = os.stat(path).st_size
        print(size)
        # send the length of the file to the client
        send(str(size), client_socket)
        read = 0
        with open(path, "rb") as file1:
            massage = file1.read(MAX_LENGTH_OF_SEND)
            read += MAX_LENGTH_OF_SEND
            while read < size:
                binary_send(massage, client_socket)
                massage = file1.read(MAX_LENGTH_OF_SEND)
                read += MAX_LENGTH_OF_SEND
        print(f"The file {path} has been sent")
    except Exception as e:
        print(f"Couldn't send file because {e}")
        return "Error: " + str(e)
    return "success sending a file"
def send(msg, client_socket):
    """ sending a massage to a client by sending the length of the massage first
    :param msg: the massage to send
    :param client_socket: the client to send the massage
    """
    client_socket.send(str(len(msg)).encode())
    client_socket.send(msg.encode())

def binary_send(msg, client_socket):
    """ sending a massage to a client by sending the length of the massage first without encoding the massage
    :param msg: the massage to send
    :param client_socket: the client to send the massage
    """
    print(f"len = {str(len(msg)).encode()}")
    client_socket.send(str(len(msg)).encode())
    client_socket.send(msg)

Here is the client code:

data = receive_msg(my_socket)
if data.startswith("Error:"):
        print(data)
else:
    if SENT_PICTURE_PATH.endswith("\\"):
        path = SENT_PICTURE_PATH + request[1]
    else:
        path = SENT_PICTURE_PATH + "\\" + request[1]
    if not os.path.exists(path):
        os.makedirs(path)
    with open(path, "wb") as file:
        size = int(data)
        given = 0
        error = False
        while not error and given < size:
            length = int(my_socket.recv(4).decode())
            print(length)
            data = my_socket.recv(length)
            print(data)
            try:
                if data.decode().startswith("Error:"):
                    error = True
                    print(data.decode())
            except UnicodeDecodeError or ValueError:
                pass
            if not error:
                file.write(data)
                size += length
def receive_msg(my_socket):
    """receive a massage from the server with a length of 99 max
    :param my_socket: the socket to get from
    :return: the massage
    """
    length = int(my_socket.recv(2).decode())
    return my_socket.recv(length).decode()
  • ``data = my_socket.recv(length)`` receives *up to* ``length`` bytes. Since the buffers for packets are usually of the order of 4096 bytes, it is likely that you receive less than ``MAX_LENGTH_OF_SEND``. That means ``data`` is likely split up, *possibly even across UTF-8 boundaries*. In short, your protocol is likely broken – it will fail to decode partial ``data``, and the ``length`` of the "next" block is garbage left over from the previous ``data``. You might want to take a look at the [Python socket programming HOWTO](https://docs.python.org/3/howto/sockets.html). – MisterMiyagi Nov 09 '20 at 08:27
  • I have just checked the length of the data received in the client and it equals the data that was sent by the server. The problem is that the server doesn't send all the data of the file because after about 2 reading calls the reading function returns an empty string because the file was ended but only 2 blocks were sent and 30 were supposed to be sent. – flikhamud45 Nov 09 '20 at 09:05
  • 1
    @MisterMiyagi has explained why this *cannot* work. Perhaps [this more detailed answer](https://stackoverflow.com/a/43420503/238704) will convince you. – President James K. Polk Nov 09 '20 at 23:51
  • @PresidentJamesK.Polk I have just fixed the problem and it works perfectly. the problem was that I write the file to the same place I read from so it overided the file. after fixing it works perfectly so I cant understand what you are talking about. – flikhamud45 Nov 11 '20 at 20:06

0 Answers0