ewalel
ewalel

Reputation: 2096

How to send big image (2MB) multiple files from server to client with UDP python socket

I want to transfer multiple images over UDP. I know it is possible using TCP, but I want it over UDP. Below is the code fragment I used. Is it possible to transfer bigger files over UDP? I manage to transfer small file sizes, but failed for large files. I appreciate any help or alternative way to do using UDP socket.

Client code receiving an image.

BUF_SIZE = 1024
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('localhost', port))
sock.settimeout(30)
def rcv_data(sock, num_packet_to_recv, file_size):
    bytes_rcvd = bytearray()
    f = open(download_dir , 'wb')
    print('Receiving packets will start')
    while num_packet_to_recv > 0:
        try:
           client_data, server_addr = sock.recvfrom(BUF_SIZE + 8)
           seq_num = client_b_data[-8:]
           img_data = client_data[:-8]
           num_packet_to_recv = num_packet_to_recv - 1
        #store img_data and seq_num to bytes_rcvd for later 
    #sorting by sequence number  
    f.write(sorted_bytes_rcvd)

    except Exception as e:
        print('rcv error {}'.format(e))
f.close()

Server side sending data

def send_img(host, port, file_name, num_pkt):
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        sock.setblocking(0)
        sock.settimeout(60)
        client_addr = (host, port)
        # send the file name
        while num_pkt > 0:
            img_part = requested_file.read(BUF_SIZE + 8)
            sock.sendto(img_part + seq_num)
            num_pkt -= 1

Upvotes: 0

Views: 2225

Answers (1)

Jeremy Friesner
Jeremy Friesner

Reputation: 73294

Your posted code seems to assume that no packets will be dropped en route from the sender to the receiver -- that assumption doesn't hold up in real life (not even when sender and receiver are both located on the same machine!), which is the most likely reason your transfers don't work except on very small files (where you can sort-of-rely on luck to ensure that all the packets make it through on the first try).

To implement a more robust mechanism, your receiver program will need some way to (a) detect when a packet has been dropped, and (b) react to that knowledge by sending a message back to the sender requesting the sender to retransmit the data from the "lost" packet. (And of course the retransmission-request-packet can also get dropped, so you'll need a way to handle that as well!)

Your sender program, meanwhile, will need to not only send the data (as it currently does) but also receive any incoming retransmit-request-packets from the receiver, and react to them by retransmitting the requested data.

Depending on the exact design of your protocol, both sender and receiver may also need to take action after a certain amount of time has passed with no data sent or received, to avoid having the file-transfer process stall out if all the packets whose reception would have advanced it get dropped.

Therefore your current approach of just calling blocking sendto() or recvfrom() in a loop won't be sufficient; instead both sender and receiver will need to implement some kind of state-machine that allows them to both send the appropriate packet(s) at the appropriate time and quickly receive and handle any packets that come in. This would typically be done either with separate sender and receiver threads, or alternatively by setting the socket to non-blocking mode and writing an event-loop around a blocking call to select() or poll(). (I prefer the latter, because IMO while state machines are tricky to get right, multithreading is even trickier)

Placing a sequence number into each packet is a good start; that allows the receiver to know how to order the data, and allows it to detect when there is a "hole" in the data it has received. Once it has detected a hole (i.e. one or more missing sequence numbers) it can send a packet back to the sender asking for those packets to be re-sent, and it will be up to the sender to react by re-sending those packets. Repeat as necessary until the receiver has received a packet with every possible sequence number (you'll also need to communicate to the receiver somehow how many sequence numbers to expect).

Upvotes: 3

Related Questions