Как отправить большое изображение (2 МБ) нескольких файлов с сервера на клиент с помощью сокета UDP Python - PullRequest
0 голосов
/ 18 декабря 2018

Я хочу передать несколько изображений по UDP.Я знаю, что это возможно с помощью TCP, но я хочу это через UDP.Ниже приведен фрагмент кода, который я использовал.Можно ли передавать большие файлы по UDP?Мне удается передать файлы небольшого размера, но для больших файлов это не удалось.Я ценю любую помощь или альтернативный способ использования UDP-сокета.

Код клиента, получающий изображение.

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()

Отправка данных на стороне сервера

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

1 Ответ

0 голосов
/ 18 декабря 2018

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

Чтобы реализовать более надежный механизм, вашей программе-получателю потребуется какой-то способ (а) определить, когда пакет был отброшен, и (б) отреагировать на это знание, отправив сообщение обратно отправителю, запрашивающемуотправитель повторно передает данные из «потерянного» пакета.(И, конечно, пакет запроса на ретрансляцию также может быть отброшен, поэтому вам также понадобится способ справиться с этим!)

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

В зависимости от точной схемы вашего протокола, отправитель и получатель могут такженеобходимо предпринять действия после того, как прошло определенное количество времени, когда данные не были отправлены или получены, чтобы избежать остановки процесса передачи файла, если все пакеты, чей прием был бы продвинут, будут отброшены.

Поэтому ваштекущего подхода к простому вызову блокировки sendto() или recvfrom() в цикле будет недостаточно;вместо этого и отправителю, и получателю потребуется реализовать некий конечный автомат, который позволит им одновременно отправлять соответствующий пакет (ы) в соответствующее время и быстро принимать и обрабатывать любые входящие пакеты. Обычно это делается с помощью отдельныхпотоки отправителя и получателя, или, альтернативно, установив сокет в неблокирующий режим и записав цикл обработки событий вокруг блокирующего вызова на select() или poll().(Я предпочитаю последнее, потому что IMO, в то время как конечные автоматы сложно найти правильное решение, многопоточность еще сложнее)

Хорошее начало - поместить порядковый номер в каждый пакет;это позволяет получателю знать, как упорядочить данные, и позволяет ему обнаруживать «дыру» в данных, которые он получил.Как только он обнаружил дыру (то есть один или несколько пропущенных порядковых номеров), он может отправить пакет обратно отправителю с просьбой повторно отправить эти пакеты, и отправителю придется отреагировать путем повторной отправки этих пакетов.,Повторяйте по мере необходимости до тех пор, пока получатель не получит пакет с каждым возможным порядковым номером (вам также необходимо каким-то образом сообщить получателю, сколько ожидаемых порядковых номеров).

...